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

import { APIResource } from '../../../../core/resource';
import * as APIKeysAPI from './api-keys';
import {
  APIKeyDeleteParams,
  APIKeyDeleteResponse,
  APIKeyListParams,
  APIKeyRetrieveParams,
  APIKeys,
  ProjectAPIKey,
  ProjectAPIKeysPage,
} from './api-keys';
import * as CertificatesAPI from './certificates';
import {
  CertificateActivateParams,
  CertificateActivateResponse,
  CertificateActivateResponsesPage,
  CertificateDeactivateParams,
  CertificateDeactivateResponse,
  CertificateDeactivateResponsesPage,
  CertificateListParams,
  CertificateListResponse,
  CertificateListResponsesPage,
  Certificates,
} from './certificates';
import * as DataRetentionAPI from './data-retention';
import { DataRetention, DataRetentionUpdateParams, ProjectDataRetention } from './data-retention';
import * as HostedToolPermissionsAPI from './hosted-tool-permissions';
import {
  HostedToolPermissionUpdateParams,
  HostedToolPermissions,
  ProjectHostedToolPermissions,
} from './hosted-tool-permissions';
import * as ModelPermissionsAPI from './model-permissions';
import {
  ModelPermissionUpdateParams,
  ModelPermissions,
  ProjectModelPermissions,
  ProjectModelPermissionsDeleted,
} from './model-permissions';
import * as RateLimitsAPI from './rate-limits';
import {
  ProjectRateLimit,
  ProjectRateLimitsPage,
  RateLimitListRateLimitsParams,
  RateLimitUpdateRateLimitParams,
  RateLimits,
} from './rate-limits';
import * as RolesAPI from './roles';
import {
  RoleCreateParams,
  RoleDeleteParams,
  RoleDeleteResponse,
  RoleListParams,
  RoleRetrieveParams,
  RoleUpdateParams,
  Roles,
} from './roles';
import * as SpendAlertsAPI from './spend-alerts';
import {
  ProjectSpendAlert,
  ProjectSpendAlertDeleted,
  ProjectSpendAlertsPage,
  SpendAlertCreateParams,
  SpendAlertDeleteParams,
  SpendAlertListParams,
  SpendAlertRetrieveParams,
  SpendAlertUpdateParams,
  SpendAlerts,
} from './spend-alerts';
import * as SpendLimitAPI from './spend-limit';
import {
  ProjectSpendLimit,
  ProjectSpendLimitDeleted,
  SpendLimit,
  SpendLimitUpdateParams,
} from './spend-limit';
import * as GroupsAPI from './groups/groups';
import {
  GroupCreateParams,
  GroupDeleteParams,
  GroupDeleteResponse,
  GroupListParams,
  GroupRetrieveParams,
  Groups,
  ProjectGroup,
  ProjectGroupsPage,
} from './groups/groups';
import * as ServiceAccountsAPI from './service-accounts/service-accounts';
import {
  ProjectServiceAccount,
  ProjectServiceAccountsPage,
  ServiceAccountCreateParams,
  ServiceAccountCreateResponse,
  ServiceAccountDeleteParams,
  ServiceAccountDeleteResponse,
  ServiceAccountListParams,
  ServiceAccountRetrieveParams,
  ServiceAccountUpdateParams,
  ServiceAccounts,
} from './service-accounts/service-accounts';
import * as UsersAPI from './users/users';
import {
  ProjectUser,
  ProjectUsersPage,
  UserCreateParams,
  UserDeleteParams,
  UserDeleteResponse,
  UserListParams,
  UserRetrieveParams,
  UserUpdateParams,
  Users,
} from './users/users';
import { APIPromise } from '../../../../core/api-promise';
import {
  ConversationCursorPage,
  type ConversationCursorPageParams,
  PagePromise,
} from '../../../../core/pagination';
import { RequestOptions } from '../../../../internal/request-options';
import { path } from '../../../../internal/utils/path';

// Recognizable options across SDK runtime versions. Keep this independent of
// private RequestOptions fields so older handwritten runtimes still compile.
const normalizeRequestOptionsForQueryKeys = new Set([
  'method',
  'path',
  'query',
  'body',
  'headers',
  'maxRetries',
  'stream',
  'timeout',
  'httpAgent',
  'fetchOptions',
  'signal',
  'idempotencyKey',
  'defaultBaseURL',
  '__metadata',
  '__binaryRequest',
  '__binaryResponse',
  '__streamClass',
  '__security',
  '__synthesizeEventData',
]);

function normalizeRequestOptionsForQuery(
  value: unknown,
  queryKeys: ReadonlyArray<string>,
  options: RequestOptions | undefined,
):
  | ({
      [K in 'headers' | 'maxRetries' | 'timeout' | 'signal' | 'idempotencyKey' | 'query']?: RequestOptions[K];
    } & {
      [
        K in
          | 'method'
          | 'path'
          | 'body'
          | 'stream'
          | 'httpAgent'
          | 'fetchOptions'
          | 'defaultBaseURL'
          | '__metadata'
          | '__binaryRequest'
          | '__binaryResponse'
          | '__streamClass'
          | '__security'
          | '__synthesizeEventData'
      ]?: never;
    })
  | undefined {
  if (typeof value !== 'object' || value === null) return undefined;
  // Optional never fields can still be explicitly undefined unless consumers
  // enable exactOptionalPropertyTypes. Snapshot data without invoking getters.
  const entries = Object.entries(Object.getOwnPropertyDescriptors(value)).filter(
    ([, descriptor]) => descriptor.enumerable && (!('value' in descriptor) || descriptor.value !== undefined),
  );
  const keys = entries.map(([key]) => key);
  const requestOnly = keys.some(
    (key) => normalizeRequestOptionsForQueryKeys.has(key) && !queryKeys.includes(key),
  );
  if (!requestOnly) return undefined;
  // Declared query fields, including stream, must use the query argument.
  // Mixing them with request-only options is ambiguous and could change the return type.
  if (
    options !== undefined ||
    keys.some((key) => !normalizeRequestOptionsForQueryKeys.has(key) || queryKeys.includes(key))
  ) {
    throw new TypeError('Query parameters and request options must be passed as separate arguments.');
  }
  // The query position must not gain authority to change the request destination
  // or transport. Those overrides require the explicit request options argument.
  if (
    keys.some(
      (key) => !['headers', 'maxRetries', 'timeout', 'signal', 'idempotencyKey', 'query'].includes(key),
    )
  ) {
    throw new TypeError('Pass transport overrides in the explicit request options argument.');
  }
  // Copy only the validated fields. Spreading value would reintroduce undefined
  // transport overrides, and deleting them would mutate the caller's object.
  return Object.fromEntries(
    entries.map(([key, descriptor]) => {
      if ('value' in descriptor) return [key, descriptor.value];
      return [key, descriptor.get ? Reflect.apply(descriptor.get, value, []) : undefined];
    }),
  ) as {
    [K in 'headers' | 'maxRetries' | 'timeout' | 'signal' | 'idempotencyKey' | 'query']?: RequestOptions[K];
  } & {
    [
      K in
        | 'method'
        | 'path'
        | 'body'
        | 'stream'
        | 'httpAgent'
        | 'fetchOptions'
        | 'defaultBaseURL'
        | '__metadata'
        | '__binaryRequest'
        | '__binaryResponse'
        | '__streamClass'
        | '__security'
        | '__synthesizeEventData'
    ]?: never;
  };
}

export class Projects extends APIResource {
  users: UsersAPI.Users = new UsersAPI.Users(this._client);
  serviceAccounts: ServiceAccountsAPI.ServiceAccounts = new ServiceAccountsAPI.ServiceAccounts(this._client);
  apiKeys: APIKeysAPI.APIKeys = new APIKeysAPI.APIKeys(this._client);
  rateLimits: RateLimitsAPI.RateLimits = new RateLimitsAPI.RateLimits(this._client);
  modelPermissions: ModelPermissionsAPI.ModelPermissions = new ModelPermissionsAPI.ModelPermissions(
    this._client,
  );
  hostedToolPermissions: HostedToolPermissionsAPI.HostedToolPermissions =
    new HostedToolPermissionsAPI.HostedToolPermissions(this._client);
  groups: GroupsAPI.Groups = new GroupsAPI.Groups(this._client);
  roles: RolesAPI.Roles = new RolesAPI.Roles(this._client);
  dataRetention: DataRetentionAPI.DataRetention = new DataRetentionAPI.DataRetention(this._client);
  spendLimit: SpendLimitAPI.SpendLimit = new SpendLimitAPI.SpendLimit(this._client);
  spendAlerts: SpendAlertsAPI.SpendAlerts = new SpendAlertsAPI.SpendAlerts(this._client);
  certificates: CertificatesAPI.Certificates = new CertificatesAPI.Certificates(this._client);

  /**
   * Create a new project in the organization. Projects can be created and archived,
   * but cannot be deleted.
   *
   * @example
   * ```ts
   * const project =
   *   await client.admin.organization.projects.create({
   *     name: 'name',
   *   });
   * ```
   */
  create(body: ProjectCreateParams, options?: RequestOptions): APIPromise<Project> {
    return this._client.post('/organization/projects', {
      body,
      ...options,
      __security: { adminAPIKeyAuth: true },
    });
  }

  /**
   * Retrieves a project.
   *
   * @example
   * ```ts
   * const project =
   *   await client.admin.organization.projects.retrieve(
   *     'project_id',
   *   );
   * ```
   */
  retrieve(projectID: string, options?: RequestOptions): APIPromise<Project> {
    return this._client.get(path`/organization/projects/${projectID}`, {
      ...options,
      __security: { adminAPIKeyAuth: true },
    });
  }

  /**
   * Modifies a project in the organization.
   *
   * @example
   * ```ts
   * const project =
   *   await client.admin.organization.projects.update(
   *     'project_id',
   *   );
   * ```
   */
  update(projectID: string, body: ProjectUpdateParams, options?: RequestOptions): APIPromise<Project> {
    return this._client.post(path`/organization/projects/${projectID}`, {
      body,
      ...options,
      __security: { adminAPIKeyAuth: true },
    });
  }

  /**
   * Returns a list of projects.
   *
   * @example
   * ```ts
   * // Automatically fetches more pages as needed.
   * for await (const project of client.admin.organization.projects.list()) {
   *   // ...
   * }
   * ```
   */
  list(
    query?:
      | (ProjectListParams &
          (
            | {
                [
                  K in
                    | 'method'
                    | 'path'
                    | 'query'
                    | 'body'
                    | 'headers'
                    | 'maxRetries'
                    | 'stream'
                    | 'timeout'
                    | 'httpAgent'
                    | 'fetchOptions'
                    | 'signal'
                    | 'idempotencyKey'
                    | 'defaultBaseURL'
                    | '__metadata'
                    | '__binaryRequest'
                    | '__binaryResponse'
                    | '__streamClass'
                    | '__security'
                    | '__synthesizeEventData'
                ]?: never;
              }
            | null
            | undefined
          ))
      | null
      | undefined,
    options?: RequestOptions,
  ): PagePromise<ProjectsPage, Project>;
  list(
    options?: {
      [K in 'headers' | 'maxRetries' | 'timeout' | 'signal' | 'idempotencyKey' | 'query']?: RequestOptions[K];
    } & {
      [
        K in
          | 'method'
          | 'path'
          | 'body'
          | 'stream'
          | 'httpAgent'
          | 'fetchOptions'
          | 'defaultBaseURL'
          | '__metadata'
          | '__binaryRequest'
          | '__binaryResponse'
          | '__streamClass'
          | '__security'
          | '__synthesizeEventData'
      ]?: never;
    },
  ): PagePromise<ProjectsPage, Project>;
  list(
    query:
      | ProjectListParams
      | ({
          [
            K in 'headers' | 'maxRetries' | 'timeout' | 'signal' | 'idempotencyKey' | 'query'
          ]?: RequestOptions[K];
        } & {
          [
            K in
              | 'method'
              | 'path'
              | 'body'
              | 'stream'
              | 'httpAgent'
              | 'fetchOptions'
              | 'defaultBaseURL'
              | '__metadata'
              | '__binaryRequest'
              | '__binaryResponse'
              | '__streamClass'
              | '__security'
              | '__synthesizeEventData'
          ]?: never;
        })
      | null
      | undefined = {},
    options?: RequestOptions,
  ): PagePromise<ProjectsPage, Project> {
    const normalizeRequestOptionsForQueryOptions = normalizeRequestOptionsForQuery(
      query,
      ['after', 'include_archived', 'limit'],
      options,
    );
    if (normalizeRequestOptionsForQueryOptions !== undefined) {
      options = normalizeRequestOptionsForQueryOptions;
      query = {};
    }
    query = query as ProjectListParams | null | undefined;
    return this._client.getAPIList('/organization/projects', ConversationCursorPage<Project>, {
      query,
      ...options,
      __security: { adminAPIKeyAuth: true },
    });
  }

  /**
   * Archives a project in the organization. Archived projects cannot be used or
   * updated.
   *
   * @example
   * ```ts
   * const project =
   *   await client.admin.organization.projects.archive(
   *     'project_id',
   *   );
   * ```
   */
  archive(projectID: string, options?: RequestOptions): APIPromise<Project> {
    return this._client.post(path`/organization/projects/${projectID}/archive`, {
      ...options,
      __security: { adminAPIKeyAuth: true },
    });
  }
}

export type ProjectsPage = ConversationCursorPage<Project>;

/**
 * Represents an individual project.
 */
export interface Project {
  /**
   * The identifier, which can be referenced in API endpoints
   */
  id: string;

  /**
   * The Unix timestamp (in seconds) of when the project was created.
   */
  created_at: number;

  /**
   * The object type, which is always `organization.project`
   */
  object: 'organization.project';

  /**
   * The Unix timestamp (in seconds) of when the project was archived or `null`.
   */
  archived_at?: number | null;

  /**
   * The external key associated with the project.
   */
  external_key_id?: string | null;

  /**
   * The name of the project. This appears in reporting.
   */
  name?: string | null;

  /**
   * The residency configuration for the project.
   */
  residency?: ProjectResidency;

  /**
   * `active` or `archived`
   */
  status?: string | null;
}

export type ProjectResidency =
  | 'GLOBAL'
  | 'US_STORAGE_PROCESSING'
  | 'EU_STORAGE_PROCESSING'
  | 'JP_STORAGE'
  | 'KR_STORAGE'
  | 'CA_STORAGE'
  | 'SG_STORAGE'
  | 'IN_STORAGE'
  | 'AU_STORAGE'
  | 'GB_STORAGE'
  | 'AE_STORAGE'
  | 'AE_STORAGE_PROCESSING';

export interface ProjectCreateParams {
  /**
   * The friendly name of the project, this name appears in reports.
   */
  name: string;

  /**
   * External key ID to associate with the project.
   */
  external_key_id?: string | null;

  /**
   * @deprecated Create the project with the specified data residency region. Your
   * organization must have access to Data residency functionality in order to use.
   * See
   * [data residency controls](https://developers.openai.com/api/docs/guides/your-data#data-residency-controls)
   * to review the functionality and limitations of setting this field. Deprecated:
   * use `residency` instead. Do not provide both `geography` and `residency`.
   */
  geography?: string | null;

  /**
   * Create the project with the specified residency configuration. Your organization
   * must have access to the requested residency configuration in order to use it.
   * See
   * [data residency controls](https://developers.openai.com/api/docs/guides/your-data#data-residency-controls)
   * to review the functionality and limitations of setting this field.
   */
  residency?: ProjectResidency | null;
}

export interface ProjectUpdateParams {
  /**
   * External key ID to associate with the project.
   */
  external_key_id?: string | null;

  /**
   * @deprecated Geography for the project. Deprecated: use `residency` when creating
   * a project to configure data residency. This field is retained for backward
   * compatibility.
   */
  geography?: string | null;

  /**
   * The updated name of the project, this name appears in reports.
   */
  name?: string | null;
}

export interface ProjectListParams extends ConversationCursorPageParams {
  /**
   * If `true` returns all projects including those that have been `archived`.
   * Archived projects are not included by default.
   */
  include_archived?: boolean;
}

Projects.Users = Users;
Projects.ServiceAccounts = ServiceAccounts;
Projects.APIKeys = APIKeys;
Projects.RateLimits = RateLimits;
Projects.ModelPermissions = ModelPermissions;
Projects.HostedToolPermissions = HostedToolPermissions;
Projects.Groups = Groups;
Projects.Roles = Roles;
Projects.DataRetention = DataRetention;
Projects.SpendLimit = SpendLimit;
Projects.SpendAlerts = SpendAlerts;
Projects.Certificates = Certificates;

export declare namespace Projects {
  export {
    type Project as Project,
    type ProjectResidency as ProjectResidency,
    type ProjectsPage as ProjectsPage,
    type ProjectCreateParams as ProjectCreateParams,
    type ProjectUpdateParams as ProjectUpdateParams,
    type ProjectListParams as ProjectListParams,
  };

  export {
    Users as Users,
    type ProjectUser as ProjectUser,
    type UserDeleteResponse as UserDeleteResponse,
    type ProjectUsersPage as ProjectUsersPage,
    type UserCreateParams as UserCreateParams,
    type UserRetrieveParams as UserRetrieveParams,
    type UserUpdateParams as UserUpdateParams,
    type UserListParams as UserListParams,
    type UserDeleteParams as UserDeleteParams,
  };

  export {
    ServiceAccounts as ServiceAccounts,
    type ProjectServiceAccount as ProjectServiceAccount,
    type ServiceAccountCreateResponse as ServiceAccountCreateResponse,
    type ServiceAccountDeleteResponse as ServiceAccountDeleteResponse,
    type ProjectServiceAccountsPage as ProjectServiceAccountsPage,
    type ServiceAccountCreateParams as ServiceAccountCreateParams,
    type ServiceAccountRetrieveParams as ServiceAccountRetrieveParams,
    type ServiceAccountUpdateParams as ServiceAccountUpdateParams,
    type ServiceAccountListParams as ServiceAccountListParams,
    type ServiceAccountDeleteParams as ServiceAccountDeleteParams,
  };

  export {
    APIKeys as APIKeys,
    type ProjectAPIKey as ProjectAPIKey,
    type APIKeyDeleteResponse as APIKeyDeleteResponse,
    type ProjectAPIKeysPage as ProjectAPIKeysPage,
    type APIKeyRetrieveParams as APIKeyRetrieveParams,
    type APIKeyListParams as APIKeyListParams,
    type APIKeyDeleteParams as APIKeyDeleteParams,
  };

  export {
    RateLimits as RateLimits,
    type ProjectRateLimit as ProjectRateLimit,
    type ProjectRateLimitsPage as ProjectRateLimitsPage,
    type RateLimitListRateLimitsParams as RateLimitListRateLimitsParams,
    type RateLimitUpdateRateLimitParams as RateLimitUpdateRateLimitParams,
  };

  export {
    ModelPermissions as ModelPermissions,
    type ProjectModelPermissions as ProjectModelPermissions,
    type ProjectModelPermissionsDeleted as ProjectModelPermissionsDeleted,
    type ModelPermissionUpdateParams as ModelPermissionUpdateParams,
  };

  export {
    HostedToolPermissions as HostedToolPermissions,
    type ProjectHostedToolPermissions as ProjectHostedToolPermissions,
    type HostedToolPermissionUpdateParams as HostedToolPermissionUpdateParams,
  };

  export {
    Groups as Groups,
    type ProjectGroup as ProjectGroup,
    type GroupDeleteResponse as GroupDeleteResponse,
    type ProjectGroupsPage as ProjectGroupsPage,
    type GroupCreateParams as GroupCreateParams,
    type GroupRetrieveParams as GroupRetrieveParams,
    type GroupListParams as GroupListParams,
    type GroupDeleteParams as GroupDeleteParams,
  };

  export {
    Roles as Roles,
    type RoleDeleteResponse as RoleDeleteResponse,
    type RoleCreateParams as RoleCreateParams,
    type RoleRetrieveParams as RoleRetrieveParams,
    type RoleUpdateParams as RoleUpdateParams,
    type RoleListParams as RoleListParams,
    type RoleDeleteParams as RoleDeleteParams,
  };

  export {
    DataRetention as DataRetention,
    type ProjectDataRetention as ProjectDataRetention,
    type DataRetentionUpdateParams as DataRetentionUpdateParams,
  };

  export {
    SpendLimit as SpendLimit,
    type ProjectSpendLimit as ProjectSpendLimit,
    type ProjectSpendLimitDeleted as ProjectSpendLimitDeleted,
    type SpendLimitUpdateParams as SpendLimitUpdateParams,
  };

  export {
    SpendAlerts as SpendAlerts,
    type ProjectSpendAlert as ProjectSpendAlert,
    type ProjectSpendAlertDeleted as ProjectSpendAlertDeleted,
    type ProjectSpendAlertsPage as ProjectSpendAlertsPage,
    type SpendAlertCreateParams as SpendAlertCreateParams,
    type SpendAlertRetrieveParams as SpendAlertRetrieveParams,
    type SpendAlertUpdateParams as SpendAlertUpdateParams,
    type SpendAlertListParams as SpendAlertListParams,
    type SpendAlertDeleteParams as SpendAlertDeleteParams,
  };

  export {
    Certificates as Certificates,
    type CertificateListResponse as CertificateListResponse,
    type CertificateActivateResponse as CertificateActivateResponse,
    type CertificateDeactivateResponse as CertificateDeactivateResponse,
    type CertificateListResponsesPage as CertificateListResponsesPage,
    type CertificateActivateResponsesPage as CertificateActivateResponsesPage,
    type CertificateDeactivateResponsesPage as CertificateDeactivateResponsesPage,
    type CertificateListParams as CertificateListParams,
    type CertificateActivateParams as CertificateActivateParams,
    type CertificateDeactivateParams as CertificateDeactivateParams,
  };
}
