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

import { APIResource } from '../../core/resource';
import * as OrganizationProfileAPI from './organization-profile';
import {
  BaseOrganizationProfileResource,
  OrganizationProfile,
  OrganizationProfileResource,
  OrganizationProfileUpdateParams,
} from './organization-profile';
import * as BillingAPI from './billing/billing';
import { BaseBilling, Billing } from './billing/billing';
import * as LogsAPI from './logs/logs';
import { BaseLogs, Logs } from './logs/logs';
import { APIPromise } from '../../core/api-promise';
import { PagePromise, SinglePage } from '../../core/pagination';
import { RequestOptions } from '../../internal/request-options';
import { path } from '../../internal/utils/path';

export class BaseOrganizations extends APIResource {
  static override readonly _key: readonly ['organizations'] = Object.freeze(['organizations'] as const);

  /**
   * Create a new organization for a user. Sub-organization creation availability
   * depends on the organization's capabilities. (Currently in Public Beta - see
   * https://developers.cloudflare.com/fundamentals/organizations/)
   */
  create(body: OrganizationCreateParams, options?: RequestOptions): APIPromise<Organization> {
    return (
      this._client.post('/organizations', { body, ...options }) as APIPromise<{ result: Organization }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Update an organization's name. (Currently in Public Beta - see
   * https://developers.cloudflare.com/fundamentals/organizations/)
   */
  update(
    organizationID: string,
    body: OrganizationUpdateParams,
    options?: RequestOptions,
  ): APIPromise<Organization> {
    return (
      this._client.put(path`/organizations/${organizationID}`, { body, ...options }) as APIPromise<{
        result: Organization;
      }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Retrieve a list of organizations a particular user has access to. (Currently in
   * Public Beta - see https://developers.cloudflare.com/fundamentals/organizations/)
   */
  list(
    query: OrganizationListParams | null | undefined = {},
    options?: RequestOptions,
  ): PagePromise<OrganizationsSinglePage, Organization> {
    return this._client.getAPIList('/organizations', SinglePage<Organization>, { query, ...options });
  }

  /**
   * Delete an organization. The organization MUST be empty before deleting. It must
   * not contain any sub-organizations, accounts, members or users. Sub-organization
   * deletion availability depends on the organization's capabilities. (Currently in
   * Public Beta - see https://developers.cloudflare.com/fundamentals/organizations/)
   *
   * **Access Control:** Restricted to enterprise organizations.
   */
  delete(organizationID: string, options?: RequestOptions): APIPromise<OrganizationDeleteResponse> {
    return (
      this._client.delete(path`/organizations/${organizationID}`, options) as APIPromise<{
        result: OrganizationDeleteResponse;
      }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Retrieve the details of a certain organization. (Currently in Public Beta - see
   * https://developers.cloudflare.com/fundamentals/organizations/)
   */
  get(organizationID: string, options?: RequestOptions): APIPromise<Organization> {
    return (
      this._client.get(path`/organizations/${organizationID}`, options) as APIPromise<{
        result: Organization;
      }>
    )._thenUnwrap((obj) => obj.result);
  }
}
export class Organizations extends BaseOrganizations {
  organizationProfile: OrganizationProfileAPI.OrganizationProfileResource =
    new OrganizationProfileAPI.OrganizationProfileResource(this._client);
  logs: LogsAPI.Logs = new LogsAPI.Logs(this._client);
  billing: BillingAPI.Billing = new BillingAPI.Billing(this._client);
}

export type OrganizationsSinglePage = SinglePage<Organization>;

/**
 * References an Organization in the Cloudflare data model.
 */
export interface Organization {
  id: string;

  create_time: string;

  meta: Organization.Meta;

  name: string;

  parent?: Organization.Parent;

  profile?: OrganizationProfileAPI.OrganizationProfile;
}

export namespace Organization {
  export interface Meta {
    /**
     * Ordered chain of organization tags from the root organization down to (and
     * including) this organization itself. Root organizations return a single-element
     * array containing their own tag; sub-organizations return
     * `[rootTag, ...intermediateTags, parentTag, selfTag]`. Useful for constructing
     * authorization scopes that need to cover every ancestor in the hierarchy.
     */
    hierarchy_tags?: Array<string>;

    managed_by?: string;

    /**
     * Enable features for Organizations.
     */
    tenant_flags?: Meta.TenantFlags;

    [k: string]: unknown;
  }

  export namespace Meta {
    /**
     * Enable features for Organizations.
     */
    export interface TenantFlags {
      account_creation: string;

      account_creation_applies_tenant_defaults: string;

      account_deletion: string;

      account_migration: string;

      account_mobility: string;

      enterprise_capability: string;

      member_management: string;

      sub_org_creation: string;
    }
  }

  export interface Parent {
    id: string;

    name: string;
  }
}

export interface OrganizationDeleteResponse {
  id: string;
}

export interface OrganizationCreateParams {
  name: string;

  parent?: OrganizationCreateParams.Parent;

  profile?: OrganizationProfileAPI.OrganizationProfileParam;
}

export namespace OrganizationCreateParams {
  export interface Parent {
    id: string;
  }
}

export interface OrganizationUpdateParams {
  name: string;

  parent?: OrganizationUpdateParams.Parent;

  profile?: OrganizationProfileAPI.OrganizationProfileParam;
}

export namespace OrganizationUpdateParams {
  export interface Parent {
    id: string;
  }
}

export interface OrganizationListParams {
  /**
   * Only return organizations with the specified IDs (ex. id=foo&id=bar). Send
   * multiple elements by repeating the query value.
   */
  id?: Array<string>;

  containing?: OrganizationListParams.Containing;

  name?: OrganizationListParams.Name;

  /**
   * The amount of items to return. Defaults to 10.
   */
  page_size?: number;

  /**
   * An opaque token returned from the last list response that when provided will
   * retrieve the next page.
   *
   * Parameters used to filter the retrieved list must remain in subsequent requests
   * with a page token.
   */
  page_token?: string;

  parent?: OrganizationListParams.Parent;
}

export namespace OrganizationListParams {
  export interface Containing {
    /**
     * Filter the list of organizations to the ones that contain this particular
     * account.
     */
    account?: string;

    /**
     * Filter the list of organizations to the ones that contain this particular
     * organization.
     */
    organization?: string;

    /**
     * Filter the list of organizations to the ones that contain this particular user.
     *
     * IMPORTANT: Just because an organization "contains" a user is not a
     * representation of any authorization or privilege to manage any resources
     * therein. An organization "containing" a user simply means the user is managed by
     * that organization.
     */
    user?: string;
  }

  export interface Name {
    /**
     * (case-insensitive) Filter the list of organizations to where the name contains a
     * particular string.
     */
    contains?: string;

    /**
     * (case-insensitive) Filter the list of organizations to where the name ends with
     * a particular string.
     */
    endsWith?: string;

    /**
     * (case-insensitive) Filter the list of organizations to where the name starts
     * with a particular string.
     */
    startsWith?: string;
  }

  export interface Parent {
    /**
     * Filter the list of organizations to the ones that are a sub-organization of the
     * specified organization.
     *
     * "null" is a valid value to provide for this parameter. It means "where an
     * organization has no parent (i.e. it is a 'root' organization)."
     */
    id?: (string & {}) | 'null';
  }
}

Organizations.OrganizationProfileResource = OrganizationProfileResource;
Organizations.BaseOrganizationProfileResource = BaseOrganizationProfileResource;
Organizations.Logs = Logs;
Organizations.BaseLogs = BaseLogs;
Organizations.Billing = Billing;
Organizations.BaseBilling = BaseBilling;

export declare namespace Organizations {
  export {
    type Organization as Organization,
    type OrganizationDeleteResponse as OrganizationDeleteResponse,
    type OrganizationsSinglePage as OrganizationsSinglePage,
    type OrganizationCreateParams as OrganizationCreateParams,
    type OrganizationUpdateParams as OrganizationUpdateParams,
    type OrganizationListParams as OrganizationListParams,
  };

  export {
    OrganizationProfileResource as OrganizationProfileResource,
    BaseOrganizationProfileResource as BaseOrganizationProfileResource,
    type OrganizationProfile as OrganizationProfile,
    type OrganizationProfileUpdateParams as OrganizationProfileUpdateParams,
  };

  export { Logs as Logs, BaseLogs as BaseLogs };

  export { Billing as Billing, BaseBilling as BaseBilling };
}
