import { CreateParams, DataProvider, HttpError, UpdateManyParams, UpdateParams } from 'ra-core';

type AttachmentParserConfig = {
  images: string[];
  files: string[];
  attachments?: string[];
};

type AttachmentParserResult = {
  data: any;
  parts: any[];
};
type ErrorMapperResult = {
  errors?: any[];
};

type CreateHeaderOptions = {
  headers: Headers | any;
  body?: any;
  user?: {
    token: string;
  };
  method: 'GET' | 'POST' | 'PUT' | 'DELETE' | string;
};

type UpdateManyParamsExtended = UpdateManyParams & {
  rows: any[];
};

type ApplicaDataProviderConfig = {
  apiUrl: string;
  getHeaders: () => Promise<Headers | any>;
  getToken: () => Promise<string>;
  HttpErrorClass: any | HttpError | Error;
  attachmentsParser: (data: any) => Promise<AttachmentParserResult>;
  prepareData?: (data: any, resource?: string, params?: CreateParams | UpdateParams | any) => any;
  /**
   * Allows to specify if the application is in mobile mode.
   * In this case the dataProvider can adopt different behaviors, especially
   * for the creation and modification calls of the records in which the use of FormData
   * is supplanted by the use of pure REST calls and the upload of the files is managed
   * separately.
   */
  mobile?: boolean;
};

type IApplicaDataProvider = DataProvider & {
  /**
   * @returns {String} Returns the url of the REST service.
   */
  getApiUrl(): string;
  /**
   * Can download a single file from the server using any
   * authentication mechanisms associated with the dataProvider (e.g. JWT passed via getHeaders).
   *
   * @param {String} resource The resource to download
   * @returns {Promise} Returns a promise that resolves with the file URL.
   *
   * @example <caption>Download a file from the server</caption>
   * const attachment = await dataProvider.getFile(`/attachments/post/1/picture/1}`);
   * const link = document.createElement('a');
   * link.href = attachment;
   * link.download = get(record, props?.title || props?.source);
   * link.click();
   *
   */
  getFile(resource: string): Promise<string>;
  /**
   * Can execute a generic GET call to the REST service.
   * The service response must contain at least 'responseCode' as expected by the applica standard.
   * Response code must be equal to 'ok' if the call was successful.
   *
   * @example
   * // Example call: users?name=Roberto
   * const data = await dataProvider.get("users", { name: "Roberto" })
   * @param resource The resource to request
   * @param params The JSON object parameters to send.
   */
  get(resource: string, params: any): Promise<any>;
  /**
   * Allows you to execute a generic POST call to the REST service.
   * The service response must contain at least 'responseCode' as expected by the applica standard.
   * Response code must be equal to 'ok' if the call was successful.
   *
   * @example
   * const data = await dataProvider.post("users", { name: "Roberto" })
   *
   * @param resource The resource to request
   * @param params The JSON object parameters to send.
   */
  post(resource: string, params: any): Promise<any>;
};

export type {
  ApplicaDataProviderConfig,
  AttachmentParserConfig,
  AttachmentParserResult,
  CreateHeaderOptions,
  ErrorMapperResult,
  IApplicaDataProvider,
  UpdateManyParamsExtended
};
