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

import type { BaseClientOptions, BaseRequestOptions } from "../../../../BaseClient.js";
import { type NormalizedClientOptionsWithAuth, normalizeClientOptionsWithAuth } from "../../../../BaseClient.js";
import { mergeHeaders, mergeOnlyDefinedHeaders } from "../../../../core/headers.js";
import * as core from "../../../../core/index.js";
import * as environments from "../../../../environments.js";
import { handleNonStatusCodeError } from "../../../../errors/handleNonStatusCodeError.js";
import * as errors from "../../../../errors/index.js";
import * as Intercom from "../../../index.js";

export declare namespace CompaniesClient {
    export interface Options extends BaseClientOptions {}

    export interface RequestOptions extends BaseRequestOptions {}
}

/**
 * Everything about your Companies
 */
export class CompaniesClient {
    protected readonly _options: NormalizedClientOptionsWithAuth<CompaniesClient.Options>;

    constructor(options: CompaniesClient.Options = {}) {
        this._options = normalizeClientOptionsWithAuth(options);
    }

    /**
     * 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}`
     *
     * @param {Intercom.RetrieveCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.retrieve({
     *         name: "my company",
     *         company_id: "12345",
     *         tag_id: "678910",
     *         segment_id: "98765",
     *         page: 1,
     *         per_page: 1
     *     })
     */
    public retrieve(
        request: Intercom.RetrieveCompanyRequest = {},
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.CompaniesRetrieveResponse> {
        return core.HttpResponsePromise.fromPromise(this.__retrieve(request, requestOptions));
    }

    private async __retrieve(
        request: Intercom.RetrieveCompanyRequest = {},
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.CompaniesRetrieveResponse>> {
        const { name, company_id: companyId, tag_id: tagId, segment_id: segmentId, page, per_page: perPage } = request;
        const _queryParams: Record<string, string | string[] | object | object[] | null> = {};
        if (name != null) {
            _queryParams.name = name;
        }

        if (companyId != null) {
            _queryParams.company_id = companyId;
        }

        if (tagId != null) {
            _queryParams.tag_id = tagId;
        }

        if (segmentId != null) {
            _queryParams.segment_id = segmentId;
        }

        if (page != null) {
            _queryParams.page = page.toString();
        }

        if (perPage != null) {
            _queryParams.per_page = perPage.toString();
        }

        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                "companies",
            ),
            method: "GET",
            headers: _headers,
            queryParameters: { ..._queryParams, ...requestOptions?.queryParams },
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.CompaniesRetrieveResponse, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/companies");
    }

    /**
     * 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 %}
     *
     * @param {Intercom.CreateOrUpdateCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.BadRequestError}
     * @throws {@link Intercom.UnauthorizedError}
     *
     * @example
     *     await client.companies.createOrUpdate({
     *         name: "my company",
     *         company_id: "company_remote_id",
     *         remote_created_at: 1374138000
     *     })
     *
     * @example
     *     await client.companies.createOrUpdate()
     */
    public createOrUpdate(
        request?: Intercom.CreateOrUpdateCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.Company> {
        return core.HttpResponsePromise.fromPromise(this.__createOrUpdate(request, requestOptions));
    }

    private async __createOrUpdate(
        request?: Intercom.CreateOrUpdateCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.Company>> {
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                "companies",
            ),
            method: "POST",
            headers: _headers,
            contentType: "application/json",
            queryParameters: requestOptions?.queryParams,
            requestType: "json",
            body: request != null ? request : undefined,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.Company, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 400:
                    throw new Intercom.BadRequestError(_response.error.body as unknown, _response.rawResponse);
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/companies");
    }

    /**
     * You can fetch a single company.
     *
     * @param {Intercom.FindCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.find({
     *         company_id: "5f4d3c1c-7b1b-4d7d-a97e-6095715c6632"
     *     })
     */
    public find(
        request: Intercom.FindCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.Company> {
        return core.HttpResponsePromise.fromPromise(this.__find(request, requestOptions));
    }

    private async __find(
        request: Intercom.FindCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.Company>> {
        const { company_id: companyId } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `companies/${core.url.encodePathParam(companyId)}`,
            ),
            method: "GET",
            headers: _headers,
            queryParameters: requestOptions?.queryParams,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.Company, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/companies/{company_id}");
    }

    /**
     * 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 %}
     *
     * @param {Intercom.UpdateCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.update({
     *         company_id: "5f4d3c1c-7b1b-4d7d-a97e-6095715c6632",
     *         body: {
     *             name: "my company",
     *             website: "http://www.mycompany.com/"
     *         }
     *     })
     *
     * @example
     *     await client.companies.update({
     *         company_id: "5f4d3c1c-7b1b-4d7d-a97e-6095715c6632",
     *         body: {}
     *     })
     */
    public update(
        request: Intercom.UpdateCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.Company> {
        return core.HttpResponsePromise.fromPromise(this.__update(request, requestOptions));
    }

    private async __update(
        request: Intercom.UpdateCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.Company>> {
        const { company_id: companyId, body: _body } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `companies/${core.url.encodePathParam(companyId)}`,
            ),
            method: "PUT",
            headers: _headers,
            contentType: "application/json",
            queryParameters: requestOptions?.queryParams,
            requestType: "json",
            body: _body != null ? _body : undefined,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.Company, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(_response.error, _response.rawResponse, "PUT", "/companies/{company_id}");
    }

    /**
     * You can delete a single company.
     *
     * @param {Intercom.DeleteCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.delete({
     *         company_id: "5f4d3c1c-7b1b-4d7d-a97e-6095715c6632"
     *     })
     */
    public delete(
        request: Intercom.DeleteCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.DeletedCompanyObject> {
        return core.HttpResponsePromise.fromPromise(this.__delete(request, requestOptions));
    }

    private async __delete(
        request: Intercom.DeleteCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.DeletedCompanyObject>> {
        const { company_id: companyId } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `companies/${core.url.encodePathParam(companyId)}`,
            ),
            method: "DELETE",
            headers: _headers,
            queryParameters: requestOptions?.queryParams,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.DeletedCompanyObject, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(_response.error, _response.rawResponse, "DELETE", "/companies/{company_id}");
    }

    /**
     * You can fetch a list of all contacts that belong to a company.
     *
     * @param {Intercom.ListAttachedContactsRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.listAttachedContacts({
     *         company_id: "5f4d3c1c-7b1b-4d7d-a97e-6095715c6632"
     *     })
     */
    public listAttachedContacts(
        request: Intercom.ListAttachedContactsRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.CompanyAttachedContacts> {
        return core.HttpResponsePromise.fromPromise(this.__listAttachedContacts(request, requestOptions));
    }

    private async __listAttachedContacts(
        request: Intercom.ListAttachedContactsRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.CompanyAttachedContacts>> {
        const { company_id: companyId } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `companies/${core.url.encodePathParam(companyId)}/contacts`,
            ),
            method: "GET",
            headers: _headers,
            queryParameters: requestOptions?.queryParams,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.CompanyAttachedContacts, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(
            _response.error,
            _response.rawResponse,
            "GET",
            "/companies/{company_id}/contacts",
        );
    }

    /**
     * You can fetch a list of all segments that belong to a company.
     *
     * @param {Intercom.ListSegmentsAttachedToCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.listAttachedSegments({
     *         company_id: "5f4d3c1c-7b1b-4d7d-a97e-6095715c6632"
     *     })
     */
    public listAttachedSegments(
        request: Intercom.ListSegmentsAttachedToCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.CompanyAttachedSegments> {
        return core.HttpResponsePromise.fromPromise(this.__listAttachedSegments(request, requestOptions));
    }

    private async __listAttachedSegments(
        request: Intercom.ListSegmentsAttachedToCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.CompanyAttachedSegments>> {
        const { company_id: companyId } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `companies/${core.url.encodePathParam(companyId)}/segments`,
            ),
            method: "GET",
            headers: _headers,
            queryParameters: requestOptions?.queryParams,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.CompanyAttachedSegments, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(
            _response.error,
            _response.rawResponse,
            "GET",
            "/companies/{company_id}/segments",
        );
    }

    /**
     * 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 %}
     *
     * @param {Intercom.ListCompaniesRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     *
     * @example
     *     await client.companies.list({
     *         page: 1,
     *         per_page: 1,
     *         order: "desc"
     *     })
     */
    public async list(
        request: Intercom.ListCompaniesRequest = {},
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.Page<Intercom.Company, Intercom.CompanyList>> {
        const list = core.HttpResponsePromise.interceptFunction(
            async (request: Intercom.ListCompaniesRequest): Promise<core.WithRawResponse<Intercom.CompanyList>> => {
                const { page, per_page: perPage, order } = request;
                const _queryParams: Record<string, string | string[] | object | object[] | null> = {};
                if (page != null) {
                    _queryParams.page = page.toString();
                }
                if (perPage != null) {
                    _queryParams.per_page = perPage.toString();
                }
                if (order != null) {
                    _queryParams.order = order;
                }
                const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
                const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
                    _authRequest.headers,
                    this._options?.headers,
                    mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
                    requestOptions?.headers,
                );
                const _response = await (this._options.fetcher ?? core.fetcher)({
                    url: core.url.join(
                        (await core.Supplier.get(this._options.baseUrl)) ??
                            (await core.Supplier.get(this._options.environment)) ??
                            environments.IntercomEnvironment.UsProduction,
                        "companies/list",
                    ),
                    method: "POST",
                    headers: _headers,
                    queryParameters: { ..._queryParams, ...requestOptions?.queryParams },
                    timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
                    maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
                    abortSignal: requestOptions?.abortSignal,
                    fetchFn: this._options?.fetch,
                    logging: this._options.logging,
                });
                if (_response.ok) {
                    return { data: _response.body as Intercom.CompanyList, rawResponse: _response.rawResponse };
                }
                if (_response.error.reason === "status-code") {
                    switch (_response.error.statusCode) {
                        case 401:
                            throw new Intercom.UnauthorizedError(
                                _response.error.body as Intercom.Error_,
                                _response.rawResponse,
                            );
                        default:
                            throw new errors.IntercomError({
                                statusCode: _response.error.statusCode,
                                body: _response.error.body,
                                rawResponse: _response.rawResponse,
                            });
                    }
                }
                return handleNonStatusCodeError(_response.error, _response.rawResponse, "POST", "/companies/list");
            },
        );
        let _offset = request?.page != null ? request?.page : 1;
        const dataWithRawResponse = await list(request).withRawResponse();
        return new core.Page<Intercom.Company, Intercom.CompanyList>({
            response: dataWithRawResponse.data,
            rawResponse: dataWithRawResponse.rawResponse,
            hasNextPage: (response) => (response?.data ?? []).length > 0,
            getItems: (response) => response?.data ?? [],
            loadPage: (_response) => {
                _offset += 1;
                return list(core.setObjectProperty(request, "page", _offset));
            },
        });
    }

    /**
     *       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 %}
     *
     * @param {Intercom.ScrollCompaniesRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     *
     * @example
     *     await client.companies.scroll({
     *         scroll_param: "scroll_param"
     *     })
     */
    public async scroll(
        request: Intercom.ScrollCompaniesRequest = {},
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.Page<Intercom.Company, Intercom.CompanyScroll | undefined>> {
        const list = core.HttpResponsePromise.interceptFunction(
            async (
                request: Intercom.ScrollCompaniesRequest,
            ): Promise<core.WithRawResponse<Intercom.CompanyScroll | undefined>> => {
                const { scroll_param: scrollParam } = request;
                const _queryParams: Record<string, string | string[] | object | object[] | null> = {};
                if (scrollParam != null) {
                    _queryParams.scroll_param = scrollParam;
                }
                const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
                const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
                    _authRequest.headers,
                    this._options?.headers,
                    mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
                    requestOptions?.headers,
                );
                const _response = await (this._options.fetcher ?? core.fetcher)({
                    url: core.url.join(
                        (await core.Supplier.get(this._options.baseUrl)) ??
                            (await core.Supplier.get(this._options.environment)) ??
                            environments.IntercomEnvironment.UsProduction,
                        "companies/scroll",
                    ),
                    method: "GET",
                    headers: _headers,
                    queryParameters: { ..._queryParams, ...requestOptions?.queryParams },
                    timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
                    maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
                    abortSignal: requestOptions?.abortSignal,
                    fetchFn: this._options?.fetch,
                    logging: this._options.logging,
                });
                if (_response.ok) {
                    return {
                        data: _response.body as Intercom.CompanyScroll | undefined,
                        rawResponse: _response.rawResponse,
                    };
                }
                if (_response.error.reason === "status-code") {
                    switch (_response.error.statusCode) {
                        case 401:
                            throw new Intercom.UnauthorizedError(
                                _response.error.body as Intercom.Error_,
                                _response.rawResponse,
                            );
                        default:
                            throw new errors.IntercomError({
                                statusCode: _response.error.statusCode,
                                body: _response.error.body,
                                rawResponse: _response.rawResponse,
                            });
                    }
                }
                return handleNonStatusCodeError(_response.error, _response.rawResponse, "GET", "/companies/scroll");
            },
        );
        const dataWithRawResponse = await list(request).withRawResponse();
        return new core.Page<Intercom.Company, Intercom.CompanyScroll | undefined>({
            response: dataWithRawResponse.data,
            rawResponse: dataWithRawResponse.rawResponse,
            hasNextPage: (response) =>
                response?.scroll_param != null &&
                !(typeof response?.scroll_param === "string" && response?.scroll_param === ""),
            getItems: (response) => response?.data ?? [],
            loadPage: (response) => {
                return list(core.setObjectProperty(request, "scroll_param", response?.scroll_param));
            },
        });
    }

    /**
     * You can attach a company to a single contact.
     *
     * @param {Intercom.AttachContactToCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.BadRequestError}
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.attachContact({
     *         contact_id: "contact_id",
     *         id: "6762f09a1bb69f9f2193bb34"
     *     })
     *
     * @example
     *     await client.companies.attachContact({
     *         contact_id: "contact_id",
     *         id: "58a430d35458202d41b1e65b"
     *     })
     *
     * @example
     *     await client.companies.attachContact({
     *         contact_id: "contact_id",
     *         id: "123"
     *     })
     */
    public attachContact(
        request: Intercom.AttachContactToCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.Company> {
        return core.HttpResponsePromise.fromPromise(this.__attachContact(request, requestOptions));
    }

    private async __attachContact(
        request: Intercom.AttachContactToCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.Company>> {
        const { contact_id: contactId, ..._body } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `contacts/${core.url.encodePathParam(contactId)}/companies`,
            ),
            method: "POST",
            headers: _headers,
            contentType: "application/json",
            queryParameters: requestOptions?.queryParams,
            requestType: "json",
            body: _body,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.Company, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 400:
                    throw new Intercom.BadRequestError(_response.error.body as unknown, _response.rawResponse);
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(
            _response.error,
            _response.rawResponse,
            "POST",
            "/contacts/{contact_id}/companies",
        );
    }

    /**
     * You can detach a company from a single contact.
     *
     * @param {Intercom.DetachContactFromCompanyRequest} request
     * @param {CompaniesClient.RequestOptions} requestOptions - Request-specific configuration.
     *
     * @throws {@link Intercom.UnauthorizedError}
     * @throws {@link Intercom.NotFoundError}
     *
     * @example
     *     await client.companies.detachContact({
     *         contact_id: "58a430d35458202d41b1e65b",
     *         company_id: "58a430d35458202d41b1e65b"
     *     })
     */
    public detachContact(
        request: Intercom.DetachContactFromCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): core.HttpResponsePromise<Intercom.Company> {
        return core.HttpResponsePromise.fromPromise(this.__detachContact(request, requestOptions));
    }

    private async __detachContact(
        request: Intercom.DetachContactFromCompanyRequest,
        requestOptions?: CompaniesClient.RequestOptions,
    ): Promise<core.WithRawResponse<Intercom.Company>> {
        const { contact_id: contactId, company_id: companyId } = request;
        const _authRequest: core.AuthRequest = await this._options.authProvider.getAuthRequest();
        const _headers: core.Fetcher.Args["headers"] = mergeHeaders(
            _authRequest.headers,
            this._options?.headers,
            mergeOnlyDefinedHeaders({ "Intercom-Version": requestOptions?.version }),
            requestOptions?.headers,
        );
        const _response = await (this._options.fetcher ?? core.fetcher)({
            url: core.url.join(
                (await core.Supplier.get(this._options.baseUrl)) ??
                    (await core.Supplier.get(this._options.environment)) ??
                    environments.IntercomEnvironment.UsProduction,
                `contacts/${core.url.encodePathParam(contactId)}/companies/${core.url.encodePathParam(companyId)}`,
            ),
            method: "DELETE",
            headers: _headers,
            queryParameters: requestOptions?.queryParams,
            timeoutMs: (requestOptions?.timeoutInSeconds ?? this._options?.timeoutInSeconds ?? 20) * 1000,
            maxRetries: requestOptions?.maxRetries ?? this._options?.maxRetries,
            abortSignal: requestOptions?.abortSignal,
            fetchFn: this._options?.fetch,
            logging: this._options.logging,
        });
        if (_response.ok) {
            return { data: _response.body as Intercom.Company, rawResponse: _response.rawResponse };
        }

        if (_response.error.reason === "status-code") {
            switch (_response.error.statusCode) {
                case 401:
                    throw new Intercom.UnauthorizedError(
                        _response.error.body as Intercom.Error_,
                        _response.rawResponse,
                    );
                case 404:
                    throw new Intercom.NotFoundError(_response.error.body as unknown, _response.rawResponse);
                default:
                    throw new errors.IntercomError({
                        statusCode: _response.error.statusCode,
                        body: _response.error.body,
                        rawResponse: _response.rawResponse,
                    });
            }
        }

        return handleNonStatusCodeError(
            _response.error,
            _response.rawResponse,
            "DELETE",
            "/contacts/{contact_id}/companies/{company_id}",
        );
    }
}
