import type Field from "@arcgis/core/layers/support/Field.js";
import type { RequestOptions } from "@arcgis/core/request/types.js";
import type { default as ExternalPortal } from "@arcgis/core/portal/Portal.js";

/**
 * Temporarily extend Portal type with internal request method until we can use the one from core
 *
 * @internal
 */
export type Portal = ExternalPortal
  & {
  request: <T>(url: string, options?: RequestOptions) => Promise<T>;
};

/** @internal */
export type Nil = null | undefined;

/** @internal */
export type DatabasePlatform = "esriDBMS_PostgreSQL" | "esriDBMS_SQLServer";

/**
 * Information about a data catalog datastore.
 *
 * @internal
 * @since 5.1
 */
export interface DataCatalogDatastoreInfo {
  /**
   * The name of the datastore.
   *
   * @internal
   * @since 5.1
   */
  name: string;
  /**
   * The datastore type.
   *
   * @internal
   * @since 5.1
   */
  type: string;
  /**
   * The datastore identifier.
   *
   * @internal
   * @since 5.1
   */
  datastoreId: string;
  /**
   * The database platform.
   *
   * @internal
   * @since 5.1
   */
  databasePlatform: DatabasePlatform;
}

/**
 * Information about a dataset in a data catalog datastore.
 *
 * @internal
 * @since 5.1
 */
export interface DataCatalogDatasetInfo {
  /**
   * The dataset name.
   *
   * @internal
   * @since 5.1
   */
  name: string;
  /**
   * The dataset type.
   *
   * @internal
   * @since 5.1
   */
  type: string;
}

/**
 * Response for the data catalog datasets endpoint.
 *
 * @internal
 * @since 5.1
 */
export interface DataCatalogDatasetsResponse {
  /**
   * The list of datasets in the datastore.
   *
   * @internal
   * @since 5.1
   */
  datasets: DataCatalogDatasetInfo[];
}

/**
 * Information about a field from a table description response.
 *
 * @internal
 * @since 5.1
 */
export interface DataCatalogFieldInfo {
  /**
   * The field name.
   *
   * @internal
   * @since 5.1
   */
  name: string;
  /**
   * The normalized field type.
   *
   * This is converted from the server's `esriFieldType*` value into the same field type family
   * used elsewhere in the editor codebase so icon and value-type helpers can operate on it.
   *
   * @internal
   * @since 5.1
   */
  type: Field["type"];
  /**
   * The raw field type returned by the tableDescription endpoint.
   *
   * @internal
   * @since 5.1
   */
  serverType: string;
  /**
   * Indicates whether the field allows null values.
   *
   * @internal
   * @since 5.1
   */
  nullable: boolean;
}

/**
 * Response for a table description request.
 *
 * @internal
 * @since 5.1
 */
export interface DataCatalogTableDescription {
  /**
   * The fields available in the table.
   *
   * @internal
   * @since 5.1
   */
  fields: DataCatalogFieldInfo[];
}

/**
 * Represents a portal data catalog datastore and provides helper methods to query
 * datastore details, datasets, and table descriptions.
 *
 * @internal
 * @since 5.1
 */
export default class DataCatalogDatastore {
  constructor(options: {
      itemId: string;
      portal: Portal;
      serviceUrl: string;
      requestOptions?: Nil | RequestOptions;
  });
  readonly itemId: string;
  readonly portal: Portal;
  readonly serviceUrl: string;
  /**
   * Fetches datasets for the datastore.
   *
   * @param options - Additional options used for the request.
   * @returns Resolves to an array of dataset information.
   * @internal
   * @since 5.1
   */
  fetchDatasets(options?: Nil | RequestOptions): Promise<DataCatalogDatasetInfo[]>;
  /**
   * Fetches information about the datastore.
   *
   * @param options - Additional options used for the request.
   * @returns Resolves to datastore information.
   * @internal
   * @since 5.1
   */
  fetchInfo(options?: Nil | RequestOptions): Promise<DataCatalogDatastoreInfo>;
  /**
   * Fetches the table description for the provided table name.
   *
   * @param tableName - The table name.
   * @param options - Additional options used for the request.
   * @returns Resolves to the table description.
   * @internal
   * @since 5.1
   */
  fetchTableDescription(tableName: string, options?: Nil | RequestOptions): Promise<DataCatalogTableDescription>;
}