import type {
  MachinePresetName,
  QueueTypeName,
  RunStatus,
  WaitpointTokenStatus,
} from "../schemas/index.js";
import type { CursorPageParams } from "./pagination.js";

export interface ImportEnvironmentVariablesParams {
  /**
   * The variables to be imported. If a variable with the same key already exists, it will be overwritten when `override` is `true`.
   *
   * To specify the variables, you can pass them in as a record of key-value pairs. e.g. `{ "key1": "value1", "key2": "value2" }`
   */
  variables: Record<string, string>;
  override?: boolean;
  /**
   * When `true`, the imported variables are created as secret (redacted) environment variables. Defaults to `false`.
   */
  isSecret?: boolean;
}

export interface CreateEnvironmentVariableParams {
  name: string;
  value: string;
}

export interface UpdateEnvironmentVariableParams {
  value: string;
}

export interface ListRunsQueryParams extends CursorPageParams {
  status?: Array<RunStatus> | RunStatus;
  taskIdentifier?: Array<string> | string;
  version?: Array<string> | string;
  from?: Date | number;
  to?: Date | number;
  period?: string;
  bulkAction?: string;
  tag?: Array<string> | string;
  schedule?: string;
  isTest?: boolean;
  batch?: string;
  /**
   * The queue type and name, or multiple of them.
   *
   * @example
   * ```ts
   * const runs = await runs.list({
   *   queue: { type: "task", name: "my-task-id" },
   * });
   *
   * // Or multiple queues
   * const runs = await runs.list({
   *   queue: [
   *     { type: "custom", name: "my-custom-queue" },
   *     { type: "task", name: "my-task-id" },
   *   ],
   * });
   * ```
   * */
  queue?: Array<QueueTypeName> | QueueTypeName;
  /** The machine name, or multiple of them. */
  machine?: Array<MachinePresetName> | MachinePresetName;
  /** The region master-queue identifier, or multiple of them. */
  region?: Array<string> | string;
}

export interface ListProjectRunsQueryParams extends CursorPageParams, ListRunsQueryParams {
  env?: Array<"dev" | "staging" | "prod"> | "dev" | "staging" | "prod";
}

type RequireAtLeastOne<T, Keys extends keyof T = keyof T> = T &
  {
    [K in Keys]-?: Required<Pick<T, K>>;
  }[Keys];

/** Same filters as runs.list(), excluding pagination. */
export type BulkActionFilter = RequireAtLeastOne<Omit<ListRunsQueryParams, keyof CursorPageParams>>;

export type BulkActionSelection =
  | { filter: BulkActionFilter; runIds?: never }
  | { runIds: string[]; filter?: never };

type BaseBulkActionOptions = BulkActionSelection & {
  name?: string;
};

type TargetRegionOption = {
  /** Region identifier to replay runs in. When omitted, each replay keeps the original run's region. */
  targetRegion?: string;
};

export type CreateBulkActionOptions =
  | (BaseBulkActionOptions & {
      action: "cancel";
      targetRegion?: never;
    })
  | (BaseBulkActionOptions & { action: "replay" } & TargetRegionOption);

export type CreateBulkCancelActionOptions = BaseBulkActionOptions & {
  targetRegion?: never;
};

export type CreateBulkReplayActionOptions = BaseBulkActionOptions & TargetRegionOption;

export type ListBulkActionsQueryParams = CursorPageParams;

export interface SubscribeToRunsQueryParams {
  tasks?: Array<string> | string;
  tags?: Array<string> | string;
  createdAt?: string;
  skipColumns?: string[];
}

export interface ListWaitpointTokensQueryParams extends CursorPageParams {
  status?: Array<WaitpointTokenStatus> | WaitpointTokenStatus;
  idempotencyKey?: string;
  tags?: Array<string> | string;
  period?: string;
  from?: Date | number;
  to?: Date | number;
}
