# 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.pagination import AsyncPager, SyncPager
from ..core.request_options import RequestOptions
from ..core.serialization import convert_and_respect_annotation_metadata
from ..core.unchecked_base_model import construct_type
from ..errors.bad_request_error import BadRequestError
from ..errors.not_found_error import NotFoundError
from ..errors.unauthorized_error import UnauthorizedError
from ..types.company_attached_contacts import CompanyAttachedContacts
from ..types.company_attached_segments import CompanyAttachedSegments
from ..types.company_list import CompanyList
from ..types.company_scroll import CompanyScroll
from ..types.create_or_update_company_request import CreateOrUpdateCompanyRequest
from ..types.deleted_company_object import DeletedCompanyObject
from ..types.error import Error
from ..types.update_company_request_body import UpdateCompanyRequestBody
from .types.companies_retrieve_response import CompaniesRetrieveResponse
from .types.company import Company

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


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

    def retrieve(
        self,
        *,
        name: typing.Optional[str] = None,
        company_id: typing.Optional[str] = None,
        tag_id: typing.Optional[str] = None,
        segment_id: typing.Optional[str] = None,
        page: typing.Optional[int] = None,
        per_page: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[CompaniesRetrieveResponse]:
        """
        You can fetch a single company by passing in `company_id` or `name`.

          `https://api.intercom.io/companies?name={name}`

          `https://api.intercom.io/companies?company_id={company_id}`

        You can fetch all companies and filter by `segment_id` or `tag_id` as a query parameter.

          `https://api.intercom.io/companies?tag_id={tag_id}`

          `https://api.intercom.io/companies?segment_id={segment_id}`

        Parameters
        ----------
        name : typing.Optional[str]
            The `name` of the company to filter by.

        company_id : typing.Optional[str]
            The `company_id` of the company to filter by.

        tag_id : typing.Optional[str]
            The `tag_id` of the company to filter by.

        segment_id : typing.Optional[str]
            The `segment_id` of the company to filter by.

        page : typing.Optional[int]
            The page of results to fetch. Defaults to first page

        per_page : typing.Optional[int]
            How many results to display per page. Defaults to 15

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

        Returns
        -------
        HttpResponse[CompaniesRetrieveResponse]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            "companies",
            method="GET",
            params={
                "name": name,
                "company_id": company_id,
                "tag_id": tag_id,
                "segment_id": segment_id,
                "page": page,
                "per_page": per_page,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompaniesRetrieveResponse,
                    construct_type(
                        type_=CompaniesRetrieveResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 create_or_update(
        self,
        *,
        request: typing.Optional[CreateOrUpdateCompanyRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Company]:
        """
        You can create or update a company.

        Companies will be only visible in Intercom when there is at least one associated user.

        Companies are looked up via `company_id` in a `POST` request, if not found via `company_id`, the new company will be created, if found, that company will be updated.

        {% admonition type="warning" name="Using `company_id`" %}
          You can set a unique `company_id` value when creating a company. However, it is not possible to update `company_id`. Be sure to set a unique value once upon creation of the company.
        {% /admonition %}

        Parameters
        ----------
        request : typing.Optional[CreateOrUpdateCompanyRequest]

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

        Returns
        -------
        HttpResponse[Company]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            "companies",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=CreateOrUpdateCompanyRequest, direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 find(
        self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[Company]:
        """
        You can fetch a single company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        HttpResponse[Company]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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,
        company_id: str,
        *,
        request: typing.Optional[UpdateCompanyRequestBody] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> HttpResponse[Company]:
        """
        You can update a single company using the Intercom provisioned `id`.

        {% admonition type="warning" name="Using `company_id`" %}
          When updating a company it is not possible to update `company_id`. This can only be set once upon creation of the company.
        {% /admonition %}

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

        request : typing.Optional[UpdateCompanyRequestBody]

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

        Returns
        -------
        HttpResponse[Company]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}",
            method="PUT",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=UpdateCompanyRequestBody, direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[DeletedCompanyObject]:
        """
        You can delete a single company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        HttpResponse[DeletedCompanyObject]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeletedCompanyObject,
                    construct_type(
                        type_=DeletedCompanyObject,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 list_attached_contacts(
        self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CompanyAttachedContacts]:
        """
        You can fetch a list of all contacts that belong to a company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        HttpResponse[CompanyAttachedContacts]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}/contacts",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompanyAttachedContacts,
                    construct_type(
                        type_=CompanyAttachedContacts,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 list_attached_segments(
        self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[CompanyAttachedSegments]:
        """
        You can fetch a list of all segments that belong to a company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        HttpResponse[CompanyAttachedSegments]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}/segments",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompanyAttachedSegments,
                    construct_type(
                        type_=CompanyAttachedSegments,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 list(
        self,
        *,
        page: typing.Optional[int] = None,
        per_page: typing.Optional[int] = None,
        order: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> SyncPager[Company, CompanyList]:
        """
        You can list companies. The company list is sorted by the `last_request_at` field and by default is ordered descending, most recently requested first.

        Note that the API does not include companies who have no associated users in list responses.

        When using the Companies endpoint and the pages object to iterate through the returned companies, there is a limit of 10,000 Companies that can be returned. If you need to list or iterate on more than 10,000 Companies, please use the [Scroll API](https://developers.intercom.com/reference#iterating-over-all-companies).
        {% admonition type="warning" name="Pagination" %}
          You can use pagination to limit the number of results returned. The default is `20` results per page.
          See the [pagination section](https://developers.intercom.com/docs/build-an-integration/learn-more/rest-apis/pagination/#pagination-for-list-apis) for more details on how to use the `starting_after` param.
        {% /admonition %}

        Parameters
        ----------
        page : typing.Optional[int]
            The page of results to fetch. Defaults to first page

        per_page : typing.Optional[int]
            How many results to return per page. Defaults to 15

        order : typing.Optional[str]
            `asc` or `desc`. Return the companies in ascending or descending order. Defaults to desc

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

        Returns
        -------
        SyncPager[Company, CompanyList]
            Successful
        """
        page = page if page is not None else 1

        _response = self._client_wrapper.httpx_client.request(
            "companies/list",
            method="POST",
            params={
                "page": page,
                "per_page": per_page,
                "order": order,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    CompanyList,
                    construct_type(
                        type_=CompanyList,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data
                _has_next = True
                _get_next = lambda: self.list(
                    page=page + 1,
                    per_page=per_page,
                    order=order,
                    request_options=request_options,
                )
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 scroll(
        self, *, scroll_param: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> SyncPager[Company, typing.Optional[CompanyScroll]]:
        """
              The `list all companies` functionality does not work well for huge datasets, and can result in errors and performance problems when paging deeply. The Scroll API provides an efficient mechanism for iterating over all companies in a dataset.

        - Each app can only have 1 scroll open at a time. You'll get an error message if you try to have more than one open per app.
        - If the scroll isn't used for 1 minute, it expires and calls with that scroll param will fail
        - If the end of the scroll is reached, "companies" will be empty and the scroll parameter will expire

        {% admonition type="info" name="Scroll Parameter" %}
          You can get the first page of companies by simply sending a GET request to the scroll endpoint.
          For subsequent requests you will need to use the scroll parameter from the response.
        {% /admonition %}
        {% admonition type="danger" name="Scroll network timeouts" %}
          Since scroll is often used on large datasets network errors such as timeouts can be encountered. When this occurs you will see a HTTP 500 error with the following message:
          "Request failed due to an internal network error. Please restart the scroll operation."
          If this happens, you will need to restart your scroll query: It is not possible to continue from a specific point when using scroll.
        {% /admonition %}

        Parameters
        ----------
        scroll_param : typing.Optional[str]


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

        Returns
        -------
        SyncPager[Company, typing.Optional[CompanyScroll]]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            "companies/scroll",
            method="GET",
            params={
                "scroll_param": scroll_param,
            },
            request_options=request_options,
        )
        try:
            if _response is None or not _response.text.strip():
                return SyncPager(has_next=False, items=[], get_next=None, response=None)
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    typing.Optional[CompanyScroll],
                    construct_type(
                        type_=typing.Optional[CompanyScroll],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data if _parsed_response is not None else []

                _has_next = False
                _get_next = None
                if _parsed_response is not None:
                    _parsed_next = _parsed_response.scroll_param
                    _has_next = _parsed_next is not None and _parsed_next != ""
                    _get_next = lambda: self.scroll(
                        scroll_param=_parsed_next,
                        request_options=request_options,
                    )
                return SyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 attach_contact(
        self, contact_id: str, *, company_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[Company]:
        """
        You can attach a company to a single contact.

        Parameters
        ----------
        contact_id : str
            The unique identifier for the contact which is given by Intercom

        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        HttpResponse[Company]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"contacts/{jsonable_encoder(contact_id)}/companies",
            method="POST",
            json={
                "id": company_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 detach_contact(
        self, contact_id: str, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> HttpResponse[Company]:
        """
        You can detach a company from a single contact.

        Parameters
        ----------
        contact_id : str
            The unique identifier for the contact which is given by Intercom

        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        HttpResponse[Company]
            Successful
        """
        _response = self._client_wrapper.httpx_client.request(
            f"contacts/{jsonable_encoder(contact_id)}/companies/{jsonable_encoder(company_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return HttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 AsyncRawCompaniesClient:
    def __init__(self, *, client_wrapper: AsyncClientWrapper):
        self._client_wrapper = client_wrapper

    async def retrieve(
        self,
        *,
        name: typing.Optional[str] = None,
        company_id: typing.Optional[str] = None,
        tag_id: typing.Optional[str] = None,
        segment_id: typing.Optional[str] = None,
        page: typing.Optional[int] = None,
        per_page: typing.Optional[int] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[CompaniesRetrieveResponse]:
        """
        You can fetch a single company by passing in `company_id` or `name`.

          `https://api.intercom.io/companies?name={name}`

          `https://api.intercom.io/companies?company_id={company_id}`

        You can fetch all companies and filter by `segment_id` or `tag_id` as a query parameter.

          `https://api.intercom.io/companies?tag_id={tag_id}`

          `https://api.intercom.io/companies?segment_id={segment_id}`

        Parameters
        ----------
        name : typing.Optional[str]
            The `name` of the company to filter by.

        company_id : typing.Optional[str]
            The `company_id` of the company to filter by.

        tag_id : typing.Optional[str]
            The `tag_id` of the company to filter by.

        segment_id : typing.Optional[str]
            The `segment_id` of the company to filter by.

        page : typing.Optional[int]
            The page of results to fetch. Defaults to first page

        per_page : typing.Optional[int]
            How many results to display per page. Defaults to 15

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

        Returns
        -------
        AsyncHttpResponse[CompaniesRetrieveResponse]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            "companies",
            method="GET",
            params={
                "name": name,
                "company_id": company_id,
                "tag_id": tag_id,
                "segment_id": segment_id,
                "page": page,
                "per_page": per_page,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompaniesRetrieveResponse,
                    construct_type(
                        type_=CompaniesRetrieveResponse,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 create_or_update(
        self,
        *,
        request: typing.Optional[CreateOrUpdateCompanyRequest] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Company]:
        """
        You can create or update a company.

        Companies will be only visible in Intercom when there is at least one associated user.

        Companies are looked up via `company_id` in a `POST` request, if not found via `company_id`, the new company will be created, if found, that company will be updated.

        {% admonition type="warning" name="Using `company_id`" %}
          You can set a unique `company_id` value when creating a company. However, it is not possible to update `company_id`. Be sure to set a unique value once upon creation of the company.
        {% /admonition %}

        Parameters
        ----------
        request : typing.Optional[CreateOrUpdateCompanyRequest]

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

        Returns
        -------
        AsyncHttpResponse[Company]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            "companies",
            method="POST",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=CreateOrUpdateCompanyRequest, direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 find(
        self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[Company]:
        """
        You can fetch a single company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        AsyncHttpResponse[Company]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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,
        company_id: str,
        *,
        request: typing.Optional[UpdateCompanyRequestBody] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncHttpResponse[Company]:
        """
        You can update a single company using the Intercom provisioned `id`.

        {% admonition type="warning" name="Using `company_id`" %}
          When updating a company it is not possible to update `company_id`. This can only be set once upon creation of the company.
        {% /admonition %}

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

        request : typing.Optional[UpdateCompanyRequestBody]

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

        Returns
        -------
        AsyncHttpResponse[Company]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}",
            method="PUT",
            json=convert_and_respect_annotation_metadata(
                object_=request, annotation=UpdateCompanyRequestBody, direction="write"
            ),
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[DeletedCompanyObject]:
        """
        You can delete a single company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        AsyncHttpResponse[DeletedCompanyObject]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    DeletedCompanyObject,
                    construct_type(
                        type_=DeletedCompanyObject,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 list_attached_contacts(
        self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CompanyAttachedContacts]:
        """
        You can fetch a list of all contacts that belong to a company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        AsyncHttpResponse[CompanyAttachedContacts]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}/contacts",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompanyAttachedContacts,
                    construct_type(
                        type_=CompanyAttachedContacts,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 list_attached_segments(
        self, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[CompanyAttachedSegments]:
        """
        You can fetch a list of all segments that belong to a company.

        Parameters
        ----------
        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        AsyncHttpResponse[CompanyAttachedSegments]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"companies/{jsonable_encoder(company_id)}/segments",
            method="GET",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    CompanyAttachedSegments,
                    construct_type(
                        type_=CompanyAttachedSegments,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 list(
        self,
        *,
        page: typing.Optional[int] = None,
        per_page: typing.Optional[int] = None,
        order: typing.Optional[str] = None,
        request_options: typing.Optional[RequestOptions] = None,
    ) -> AsyncPager[Company, CompanyList]:
        """
        You can list companies. The company list is sorted by the `last_request_at` field and by default is ordered descending, most recently requested first.

        Note that the API does not include companies who have no associated users in list responses.

        When using the Companies endpoint and the pages object to iterate through the returned companies, there is a limit of 10,000 Companies that can be returned. If you need to list or iterate on more than 10,000 Companies, please use the [Scroll API](https://developers.intercom.com/reference#iterating-over-all-companies).
        {% admonition type="warning" name="Pagination" %}
          You can use pagination to limit the number of results returned. The default is `20` results per page.
          See the [pagination section](https://developers.intercom.com/docs/build-an-integration/learn-more/rest-apis/pagination/#pagination-for-list-apis) for more details on how to use the `starting_after` param.
        {% /admonition %}

        Parameters
        ----------
        page : typing.Optional[int]
            The page of results to fetch. Defaults to first page

        per_page : typing.Optional[int]
            How many results to return per page. Defaults to 15

        order : typing.Optional[str]
            `asc` or `desc`. Return the companies in ascending or descending order. Defaults to desc

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

        Returns
        -------
        AsyncPager[Company, CompanyList]
            Successful
        """
        page = page if page is not None else 1

        _response = await self._client_wrapper.httpx_client.request(
            "companies/list",
            method="POST",
            params={
                "page": page,
                "per_page": per_page,
                "order": order,
            },
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    CompanyList,
                    construct_type(
                        type_=CompanyList,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data
                _has_next = True

                async def _get_next():
                    return await self.list(
                        page=page + 1,
                        per_page=per_page,
                        order=order,
                        request_options=request_options,
                    )

                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 scroll(
        self, *, scroll_param: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncPager[Company, typing.Optional[CompanyScroll]]:
        """
              The `list all companies` functionality does not work well for huge datasets, and can result in errors and performance problems when paging deeply. The Scroll API provides an efficient mechanism for iterating over all companies in a dataset.

        - Each app can only have 1 scroll open at a time. You'll get an error message if you try to have more than one open per app.
        - If the scroll isn't used for 1 minute, it expires and calls with that scroll param will fail
        - If the end of the scroll is reached, "companies" will be empty and the scroll parameter will expire

        {% admonition type="info" name="Scroll Parameter" %}
          You can get the first page of companies by simply sending a GET request to the scroll endpoint.
          For subsequent requests you will need to use the scroll parameter from the response.
        {% /admonition %}
        {% admonition type="danger" name="Scroll network timeouts" %}
          Since scroll is often used on large datasets network errors such as timeouts can be encountered. When this occurs you will see a HTTP 500 error with the following message:
          "Request failed due to an internal network error. Please restart the scroll operation."
          If this happens, you will need to restart your scroll query: It is not possible to continue from a specific point when using scroll.
        {% /admonition %}

        Parameters
        ----------
        scroll_param : typing.Optional[str]


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

        Returns
        -------
        AsyncPager[Company, typing.Optional[CompanyScroll]]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            "companies/scroll",
            method="GET",
            params={
                "scroll_param": scroll_param,
            },
            request_options=request_options,
        )
        try:
            if _response is None or not _response.text.strip():
                return AsyncPager(has_next=False, items=[], get_next=None, response=None)
            if 200 <= _response.status_code < 300:
                _parsed_response = typing.cast(
                    typing.Optional[CompanyScroll],
                    construct_type(
                        type_=typing.Optional[CompanyScroll],  # type: ignore
                        object_=_response.json(),
                    ),
                )
                _items = _parsed_response.data if _parsed_response is not None else []

                _has_next = False
                _get_next = None
                if _parsed_response is not None:
                    _parsed_next = _parsed_response.scroll_param
                    _has_next = _parsed_next is not None and _parsed_next != ""

                    async def _get_next():
                        return await self.scroll(
                            scroll_param=_parsed_next,
                            request_options=request_options,
                        )

                return AsyncPager(has_next=_has_next, items=_items, get_next=_get_next, response=_parsed_response)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 attach_contact(
        self, contact_id: str, *, company_id: str, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[Company]:
        """
        You can attach a company to a single contact.

        Parameters
        ----------
        contact_id : str
            The unique identifier for the contact which is given by Intercom

        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        AsyncHttpResponse[Company]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"contacts/{jsonable_encoder(contact_id)}/companies",
            method="POST",
            json={
                "id": company_id,
            },
            headers={
                "content-type": "application/json",
            },
            request_options=request_options,
            omit=OMIT,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 400:
                raise BadRequestError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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 detach_contact(
        self, contact_id: str, company_id: str, *, request_options: typing.Optional[RequestOptions] = None
    ) -> AsyncHttpResponse[Company]:
        """
        You can detach a company from a single contact.

        Parameters
        ----------
        contact_id : str
            The unique identifier for the contact which is given by Intercom

        company_id : str
            The unique identifier for the company which is given by Intercom

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

        Returns
        -------
        AsyncHttpResponse[Company]
            Successful
        """
        _response = await self._client_wrapper.httpx_client.request(
            f"contacts/{jsonable_encoder(contact_id)}/companies/{jsonable_encoder(company_id)}",
            method="DELETE",
            request_options=request_options,
        )
        try:
            if 200 <= _response.status_code < 300:
                _data = typing.cast(
                    Company,
                    construct_type(
                        type_=Company,  # type: ignore
                        object_=_response.json(),
                    ),
                )
                return AsyncHttpResponse(response=_response, data=_data)
            if _response.status_code == 401:
                raise UnauthorizedError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        Error,
                        construct_type(
                            type_=Error,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            if _response.status_code == 404:
                raise NotFoundError(
                    headers=dict(_response.headers),
                    body=typing.cast(
                        typing.Any,
                        construct_type(
                            type_=typing.Any,  # type: ignore
                            object_=_response.json(),
                        ),
                    ),
                )
            _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)
