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

import { APIResource } from '../../../core/resource';
import * as Shared from '../../shared';
import { SubscriptionsSinglePage } from '../../shared';
import * as ActionsAPI from './actions';
import { ActionAppendParams, Actions, BaseActions } from './actions';
import * as BulkAPI from './bulk';
import { BaseBulk, Bulk, BulkCreateParams, BulkCreateResponse } from './bulk';
import * as CancelReasonAPI from './cancel-reason';
import {
  BaseCancelReason,
  CancelReason,
  CancelReasonCreateParams,
  CancelReasonCreateResponse,
  CancelReasonGetParams,
  CancelReasonGetResponse,
} from './cancel-reason';
import { APIPromise } from '../../../core/api-promise';
import { CloudflareError } from '../../../core/error';
import { PagePromise, SinglePage } from '../../../core/pagination';
import { RequestOptions } from '../../../internal/request-options';
import { path } from '../../../internal/utils/path';

export class BaseSubscriptions extends APIResource {
  static override readonly _key: readonly ['accounts', 'subscriptions'] = Object.freeze([
    'accounts',
    'subscriptions',
  ] as const);

  /**
   * Creates an account or zone subscription.
   *
   * @example
   * ```ts
   * const subscription =
   *   await client.accounts.subscriptions.create({
   *     account_id: 'account_id',
   *   });
   * ```
   */
  create(params: SubscriptionCreateParams, options?: RequestOptions): APIPromise<Shared.Subscription> {
    const { account_id, zone_id, ...body } = params;
    if (!account_id && !zone_id) {
      throw new CloudflareError('You must provide either account_id or zone_id.');
    }
    if (account_id && zone_id) {
      throw new CloudflareError('You cannot provide both account_id and zone_id.');
    }
    const { accountOrZone, accountOrZoneId } =
      account_id ?
        {
          accountOrZone: 'accounts',
          accountOrZoneId: account_id,
        }
      : {
          accountOrZone: 'zones',
          accountOrZoneId: zone_id,
        };
    return (
      this._client.post(path`/${accountOrZone}/${accountOrZoneId}/subscriptions`, {
        body,
        ...options,
      }) as APIPromise<{ result: Shared.Subscription }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Updates an account subscription.
   *
   * @example
   * ```ts
   * const subscription =
   *   await client.accounts.subscriptions.update(
   *     '506e3185e9c882d175a2d0cb0093d9f2',
   *     { account_id: '023e105f4ecef8ad9ca31a8372d0c353' },
   *   );
   * ```
   */
  update(
    subscriptionIdentifier: string,
    params: SubscriptionUpdateParams,
    options?: RequestOptions,
  ): APIPromise<Shared.Subscription> {
    const { account_id, ...body } = params;
    return (
      this._client.put(path`/accounts/${account_id}/subscriptions/${subscriptionIdentifier}`, {
        body,
        ...options,
      }) as APIPromise<{ result: Shared.Subscription }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Deletes an account's subscription.
   *
   * @example
   * ```ts
   * const subscription =
   *   await client.accounts.subscriptions.delete(
   *     '506e3185e9c882d175a2d0cb0093d9f2',
   *     { account_id: '023e105f4ecef8ad9ca31a8372d0c353' },
   *   );
   * ```
   */
  delete(
    subscriptionIdentifier: string,
    params: SubscriptionDeleteParams,
    options?: RequestOptions,
  ): APIPromise<SubscriptionDeleteResponse> {
    const { account_id } = params;
    return (
      this._client.delete(
        path`/accounts/${account_id}/subscriptions/${subscriptionIdentifier}`,
        options,
      ) as APIPromise<{ result: SubscriptionDeleteResponse }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Cancels pending delayed downgrades for the specified subscriptions.
   *
   * @example
   * ```ts
   * const response =
   *   await client.accounts.subscriptions.cancelDowngrade({
   *     account_id: '023e105f4ecef8ad9ca31a8372d0c353',
   *   });
   * ```
   */
  cancelDowngrade(
    params: SubscriptionCancelDowngradeParams,
    options?: RequestOptions,
  ): APIPromise<SubscriptionCancelDowngradeResponse> {
    const { account_id, ...body } = params;
    return (
      this._client.post(path`/accounts/${account_id}/subscriptions/cancel-downgrade`, {
        body,
        ...options,
      }) as APIPromise<{ result: SubscriptionCancelDowngradeResponse }>
    )._thenUnwrap((obj) => obj.result);
  }

  /**
   * Lists all of an account or zone's subscriptions.
   *
   * @example
   * ```ts
   * // Automatically fetches more pages as needed.
   * for await (const subscription of client.accounts.subscriptions.get(
   *   { account_id: 'account_id' },
   * )) {
   *   // ...
   * }
   * ```
   */
  get(
    params: SubscriptionGetParams | null | undefined = {},
    options?: RequestOptions,
  ): PagePromise<SubscriptionsSinglePage, Shared.Subscription> {
    const { account_id, zone_id } = params ?? {};
    if (!account_id && !zone_id) {
      throw new CloudflareError('You must provide either account_id or zone_id.');
    }
    if (account_id && zone_id) {
      throw new CloudflareError('You cannot provide both account_id and zone_id.');
    }
    const { accountOrZone, accountOrZoneId } =
      account_id ?
        {
          accountOrZone: 'accounts',
          accountOrZoneId: account_id,
        }
      : {
          accountOrZone: 'zones',
          accountOrZoneId: zone_id,
        };
    return this._client.getAPIList(
      path`/${accountOrZone}/${accountOrZoneId}/subscriptions`,
      SinglePage<Shared.Subscription>,
      options,
    );
  }

  /**
   * Gets an account subscription by identifier.
   *
   * @example
   * ```ts
   * const subscription =
   *   await client.accounts.subscriptions.getByIdentifier(
   *     '506e3185e9c882d175a2d0cb0093d9f2',
   *     { account_id: '023e105f4ecef8ad9ca31a8372d0c353' },
   *   );
   * ```
   */
  getByIdentifier(
    subscriptionIdentifier: string,
    params: SubscriptionGetByIdentifierParams,
    options?: RequestOptions,
  ): APIPromise<Shared.Subscription> {
    const { account_id } = params;
    return (
      this._client.get(
        path`/accounts/${account_id}/subscriptions/${subscriptionIdentifier}`,
        options,
      ) as APIPromise<{ result: Shared.Subscription }>
    )._thenUnwrap((obj) => obj.result);
  }
}
export class Subscriptions extends BaseSubscriptions {
  cancelReason: CancelReasonAPI.CancelReason = new CancelReasonAPI.CancelReason(this._client);
  actions: ActionsAPI.Actions = new ActionsAPI.Actions(this._client);
  bulk: BulkAPI.Bulk = new BulkAPI.Bulk(this._client);
}

export interface SubscriptionDeleteResponse {
  /**
   * Subscription identifier tag.
   */
  subscription_id?: string;
}

export type SubscriptionCancelDowngradeResponse = unknown | string | null;

export interface SubscriptionCreateParams {
  /**
   * Path param: The Account ID to use for this endpoint. Mutually exclusive with the
   * Zone ID.
   */
  account_id?: string;

  /**
   * Path param: The Zone ID to use for this endpoint. Mutually exclusive with the
   * Account ID.
   */
  zone_id?: string;

  /**
   * Body param: How often the subscription is renewed automatically.
   */
  frequency?: 'weekly' | 'monthly' | 'quarterly' | 'yearly';

  /**
   * Body param: The rate plan applied to the subscription.
   */
  rate_plan?: Shared.RatePlanParam;
}

export interface SubscriptionUpdateParams {
  /**
   * Path param: Identifier
   */
  account_id: string;

  /**
   * Body param: How often the subscription is renewed automatically.
   */
  frequency?: 'weekly' | 'monthly' | 'quarterly' | 'yearly';

  /**
   * Body param: The rate plan applied to the subscription.
   */
  rate_plan?: Shared.RatePlanParam;
}

export interface SubscriptionDeleteParams {
  /**
   * Identifier
   */
  account_id: string;
}

export interface SubscriptionCancelDowngradeParams {
  /**
   * Path param: Identifier
   */
  account_id: string;

  /**
   * Body param: List of subscription identifiers to cancel downgrades for.
   */
  subscription_ids?: Array<string>;
}

export interface SubscriptionGetParams {
  /**
   * The Account ID to use for this endpoint. Mutually exclusive with the Zone ID.
   */
  account_id?: string;

  /**
   * The Zone ID to use for this endpoint. Mutually exclusive with the Account ID.
   */
  zone_id?: string;
}

export interface SubscriptionGetByIdentifierParams {
  /**
   * Identifier
   */
  account_id: string;
}

Subscriptions.CancelReason = CancelReason;
Subscriptions.BaseCancelReason = BaseCancelReason;
Subscriptions.Actions = Actions;
Subscriptions.BaseActions = BaseActions;
Subscriptions.Bulk = Bulk;
Subscriptions.BaseBulk = BaseBulk;

export declare namespace Subscriptions {
  export {
    type SubscriptionDeleteResponse as SubscriptionDeleteResponse,
    type SubscriptionCancelDowngradeResponse as SubscriptionCancelDowngradeResponse,
    type SubscriptionCreateParams as SubscriptionCreateParams,
    type SubscriptionUpdateParams as SubscriptionUpdateParams,
    type SubscriptionDeleteParams as SubscriptionDeleteParams,
    type SubscriptionCancelDowngradeParams as SubscriptionCancelDowngradeParams,
    type SubscriptionGetParams as SubscriptionGetParams,
    type SubscriptionGetByIdentifierParams as SubscriptionGetByIdentifierParams,
  };

  export {
    CancelReason as CancelReason,
    BaseCancelReason as BaseCancelReason,
    type CancelReasonCreateResponse as CancelReasonCreateResponse,
    type CancelReasonGetResponse as CancelReasonGetResponse,
    type CancelReasonCreateParams as CancelReasonCreateParams,
    type CancelReasonGetParams as CancelReasonGetParams,
  };

  export { Actions as Actions, BaseActions as BaseActions, type ActionAppendParams as ActionAppendParams };

  export {
    Bulk as Bulk,
    BaseBulk as BaseBulk,
    type BulkCreateResponse as BulkCreateResponse,
    type BulkCreateParams as BulkCreateParams,
  };
}

export { type SubscriptionsSinglePage };
