/* eslint-disable @typescript-eslint/no-empty-object-type */
export type ExtFilters =
  | 'folder'
  | 'site'
  | 'documentLibrary'
  | 'list'
  | 'onenote'
  | 'file'
  | 'media'
  | 'photo'
  | 'video'
  | 'audio'
  | 'document'
  | 'listItem'
  | 'playlist'
  | 'syntexTemplate'
  | 'syntexSnippet'
  | 'syntexField'
  | `.${string}`;

//NOTE: IItem type references the following docs: https://learn.microsoft.com/en-us/graph/api/resources/driveitem?view=graph-rest-1.0#properties
export type IItem = Record<string, any>;
export type SPPickerConfig = {
  sdk: '8.0';
  /**
   * Establishes the messaging parameters used to setup the post message communications between
   * picker and host application
   */
  messaging: {
    /**
     * A unique id assigned by the host app to this File Picker instance.
     * This should ideally be a new GUID generated by the host.
     */
    channelId: string;
    /**
     * The host app's authority, used as the target origin for post-messaging.
     */
    origin: string;
    /**
     * Whether or not the host app window will need to identify itself.
     */
    identifyParent?: boolean;
    /**
     * Whether or not the client app must wait for a 'configure' command to be sent by the host before rendering.
     */
    waitForConfiguration?: boolean;
    /**
     * Override timeout for acknowledgement messages.
     */
    acknowledgeTimeout?: number;
    /**
     * Override timeout for the initialization handshake.
     */
    initializeTimeout?: number;
    /**
     * Override timeout for command responses.
     */
    resultTimeout?: number;
  };
  /**
   * Configuration for the entry location to which the File Picker will navigate on load.
   * The File Picker app will prioritize path-based navigation if provided, falling back to other address forms
   * on error (in case of Site redirection or content rename) or if path information is not provided.
   */
  entry: {
    sharePoint?: {
      /**
       * Specify an exact SharePoint content location by path segments.
       */
      byPath?: {
        /**
         * Full URL to the root of a Web, or server-relative URL.
         * @example
         *  'https://contoso-my.sharepoint.com/personal/user_contoso_com'
         * @example
         *  '/path/to/web'
         * @example
         *  'subweb'
         */
        web?: string;
        /**
         * Full URL or path segement to identity a List.
         * If not preceded with a `/` or a URL scheme, this is assumed to be a list in the specified web.
         * @example
         *  'Shared Documents'
         * @example
         *  '/path/to/web/Shared Documents'
         * @example
         *  'https://contoso.sharepoint.com/path/to/web/Shared Documents'
         */
        list?: string;
        /**
         * Path segment to a folder within a list, or a server-relative URL to a folder.
         * @example
         *  'General'
         * @example
         *  'foo/bar'
         * @example
         *  '/path/to/web/Shared Documents/General'
         */
        folder?: string;
        /**
         * Auto fallback to root folder if the specified entry sub folder doesn't exist.
         */
        fallbackToRoot?: boolean;
      };
    };
    /**
     * Indicates that File Picker should start in the Site Pivot
     * This pivot is only supported in OneDrive for Business
     */
    site?: {};
    /**
     * Indicates that File Picker should start in the OAL (My Organization) Pivot
     * This pivot is only supported in OneDrive for Business
     */
    myOrganization?: {};
    /**
     * Indicates that the File Picker should start in the user's OneDrive.
     */
    oneDrive?: {
      /**
       * Specifies that File Picker should start in the user's Files tab.
       */
      files?: {
        /**
         * Path segment for sub-folder within the user's OneDrive for Business.
         * @example
         *  'Pictures'
         * @example
         *  '/personal/user_contoso_com/Documents/Attachments'
         */
        folder?: string;
        /**
         * Auto fallback to root folder if the specified entry sub folder doesn't exist.
         */
        fallbackToRoot?: boolean;
      };
      /**
       * Indicates that File Picker should start in the user's recent files.
       */
      recent?: {};
      /**
       * Indicates that File Picker should start in the files shared with the user.
       */
      sharedWithMe?: {};
      /**
       * Indicates that File Picker should start in the user's photos.
       * This pivot is only available in OneDrive for Consumer
       */
      photos?: {};
    };
    sortBy?: {
      /**
       * Name of the field *in SharePoint* on which to sort.
       */
      fieldName: string;
      /**
       * Whether or not to sort in ascending order. Default is `true`.
       */
      isAscending?: boolean;
    };
    filterBy?: {
      /**
       * Name of the field *in SharePoint* on which to filter on.
       */
      fieldName: string;
      /**
       * Filter value
       */
      value: string;
    };
  };
  /**
   * Specifies how to enable a Search behavior.
   */
  search?: {
    enabled: boolean;
  };
  /**
   * Configuration for handling authentication requests from the embedded app.
   * Presence of this object (even if empty) indicates that the host will handle authentication.
   * Omitting this will make the embedded content attempt to rely on cookies.
   */
  authentication?: {
    /**
     * @default true
     */
    enabled?: boolean;
    /**
     * Indicates support for individual token types.
     */
    tokens?: {
      /**
       * @defaultValue true
       */
      graph?: boolean;
      /**
       * @defaultValue true
       */
      sharePoint?: boolean;
      /**
       * @defaultValue false
       */
      substrate?: boolean;
    };
    /**
     * Indicates that the host app can handle 'claims' challenges.
     */
    claimsChallenge?: {
      /**
       * @default false
       */
      enabled?: boolean;
    };
  };
  /**
   * Configures what types of items are allowed to be picked within the experience.
   * Note that the default configuration accounts for the expected authentication capabilities of the host app.
   * Depending on what else is enabled by the host, the host may be expected to provide tokens for more services and scopes.
   */
  typesAndSources?: {
    /**
     * Specifies the general category of items picked. Switches between 'file' vs. 'folder' picker mode,
     * or a general-purpose picker.
     * @default 'all'
     */
    mode?: 'files' | 'folders' | 'all';
    /**
     * `filters` options: file extension, i.e. .xlsx, .docx, .ppt, etc.
     * `filters` options: 'photo', 'folder', 'video', 'documentLibrary'
     */
    filters?: ExtFilters[];
    /**
     * Specifies a filter for *where* the item may come from.
     */
    locations?: {
      /**
       * Items may only come from the user's OneDrive.
       */
      oneDrive?: {};
      /**
       * Items may only come from a specific location within SharePoint.
       */
      sharePoint?: {
        byPath?: {
          web?: string;
          list?: string;
          folder?: string;
        };
      };
    };
    /**
     * Specifies filtering based on user access level.
     */
    access?: {
      /**
       * Filter for requires user access level for picked items. Default is `'read'`.
       */
      mode?: 'read' | 'read-write';
    };
    /**
     * Specifies which pivots the user may access while browsing files and lists.
     * Note that if a pivot is disabled here but still targeted in `entry`, it will still be visible in the nav.
     */
    pivots?: {
      /**
       * Show "My files".
       */
      oneDrive?: boolean;
      /**
       * Show "Recent".
       */
      recent?: boolean;
      /**
       * Show "Shared"
       */
      shared?: boolean;
      /**
       * Show "Quick access".
       */
      sharedLibraries?: boolean;
      /**
       * Show "My organization".
       * This pivot is only supported in OneDrive for Business
       */
      myOrganization?: boolean;
      /**
       * Show the site pivot
       * This pivot is only supported in OneDrive for Business
       */
      site?: boolean;
    };
  };
  /**
   * Configuration for what item types may be selected within the picker and returned to the host.
   */
  selection?: {
    /**
     * Controls how selection works within the list.
     * @default 'single' for the Picker.
     */
    mode?: 'single' | 'multiple' | 'pick';
    /**
     * Whether or not to allow the user to maintain a selection across folders and pivots.
     */
    enablePersistence?: boolean;
    /**
     * Whether or not the host expects to be notified whenever selection changes.
     */
    enableNotifications?: boolean;
    /**
     * The maximum number of items which may be selected.
     */
    maximumCount?: number;
    /**
     * A set of items to pre-select.
     */
    sourceItems?: IItem[];
  };
  /**
   * Configures how commands behave within the experience.
   */
  commands?: {
    /**
     * Specifies the behavior for file-picking.
     */
    pick?: {
      /**
       * A special action to perform when picking the file, before handing the result
       * back to the host app.
       */
      action?: 'select' | 'share' | 'download' | 'move';
      /**
       * A custom label to apply to the button which picks files.
       * This must be localized by the host app if supplied.
       */
      label?: string;
      /**
       * Configures the 'move' action for picking files.
       */
      move?: {
        sourceItems?: IItem[];
      };
      /**
       * Configures the 'copy' action for picking files.
       */
      copy?: {
        sourceItems?: IItem[];
      };
      /**
       * Configures the 'select' action for picking files.
       */
      select?: {
        /**
         * Specify if we want download urls to be returned when items are selected.
         */
        urls?: {
          download?: boolean;
        };
      };
    };
    /**
     * Specifies the behavior for closing the experience.
     */
    close?: {
      /**
       * A custom label to apply to the 'cancel' button.
       * This must be localized by the host app if supplied.
       */
      label?: string;
    };
    /**
     * Behavior for a "Browse this device" command to pick local files.
     */
    browseThisDevice?: {
      enabled?: boolean;
      label?: string;
      mode?: 'upload' | 'pick';
    };
    /**
     * Behavior for a "From a link" command to pick from a link.
     */
    fromALink?: {
      enabled?: boolean;
      mode?: 'nav' | 'pivot';
    };
    /**
     * Behavior for a "Switch account" command.
     */
    switchAccount?: {
      mode?: 'host' | 'none';
    };
    /**
     * Behavior for a "Manage accounts" command.
     */
    manageAccounts?: {
      mode?: 'host' | 'none';
      label?: string;
    };
    /**
     * Behavior for "Upload"
     */
    upload?: {
      enabled?: boolean;
    };
    /**
     * Behavior for "Create folder"
     */
    createFolder?: {
      enabled?: boolean;
    };
    /**
     * Behavior for "Filter by" in the column headers.
     */
    filterByColumn?: {
      mode?: 'panel' | 'menu';
    };
    /**
     * How to handle actions defined by custom formatters.
     */
    customFormatter?: {
      actions?: {
        key: string;
        mode?: 'host' | 'none';
      }[];
    };
    /**
     * How to handle specified values for `key` in custom commands
     * in the tray, nav, or command bar.
     */
    custom?: {
      actions?: {
        key: string;
        /**
         * Filters defining what types of items the action operates on.
         * If specified, the action will only be available for items which match the given filters.
         */
        filters?: ExtFilters[];
        /**
         * How the action is invoked.
         * 'host': Invokes a `custom` command message against the host app.
         * 'none': Disables the action.
         */
        mode?: 'host' | 'none';
        /**
         * Selection criteria to which the item applies.
         */
        selection?: 'single' | 'multiple' | 'current' | 'none';
      }[];
    };
  };
  /**
   * Specifies accessibility cues such as auto-focus behaviors.
   */
  accessibility?: {
    /**
     * Whether or not to 'trap focus' within the component. If this is enabled, tab-stops will loop from the last element back to the left navigation automatically.
     * This is useful if the components's frame is hosted as the only content of a modal overlay and focus should not jump to the outside content.
     *
     * @default false
     */
    enableFocusTrap?: boolean;
    /**
     * Whether or not the component should immediately grab focus once the content has loaded.
     *
     * @default true
     */
    trapFocusOnLoad?: boolean;
    /**
     * Whether or not to force the currently-focused element within the component to be highlighted.
     * By default, the focused element is highlighted if the user navigates elements with the keyboard but not when the user interacts via the mouse.
     * However, if a host application launches the component due to keyboard input it should set this flag to `true` to ensure continuity of behavior.
     *
     * @default false
     */
    showFocusOnLoad?: boolean;
  };
  tray?: {
    /**
     * Configures the commands normally used to pick files or close the picker.
     */
    commands?: {
      /**
       * A key to differentiate the command from others.
       */
      key: string;
      /**
       * A custom string for the command.
       * Must be localized by the host.
       */
      label?: string;
      /**
       * The action to perform when the button is clicked.
       */
      action: 'pick' | 'close' | 'custom';
      /**
       * If `'pick'` is specified, which pick behavior to use.
       */
      pick?: {
        action: 'select' | 'share' | 'download' | 'move';
      };
      /**
       * Whether the button should show as the primary button.
       */
      primary?: boolean;
      /**
       * Whether the button should remain visible at all times even if unavailable.
       */
      permanent?: boolean;
    }[];
    /**
     * Whether or not the picker tray might be provided by the host instead.
     * @defaultValue 'default'
     */
    mode?: 'host' | 'default';
    /**
     * Configures a component to render in the picker tray to the left of the commands.
     * @default 'selection-summary'
     */
    prompt?: 'keep-sharing' | 'selection-summary' | 'selection-editor' | 'save-as' | 'none';
    /**
     * Configures use of the 'save-as' prompt.
     */
    saveAs?: {
      /**
       * Default file name to show in 'save-as' prompt.
       */
      fileName?: string;
    };
    /**
     * Settings for handling conflicts with existing file names.
     */
    conflicts?: {
      /**
       * How to handle when a file name matches an existing file.
       * `'warn'` - Show a prompt to ask the user to confirm the choice.
       * `'block'` - Block the choice as an error.
       * `'accept'` - Accept the choice automatically.
       * `'none'` - Do not try to match with existing items.
       */
      mode?: 'warn' | 'block' | 'accept' | 'none';
    };
    /**
     * Configures use of the 'keep-sharing' prompt.
     */
    keepSharing?: {
      active?: boolean;
    };
  };
  leftNav?: {
    /**
     * Whether or not a Left Nav should be rendered by the embedded content.
     */
    enabled?: boolean;
    /**
     * Mode of presentation of the nav.
     * If the nav is enabled but this is set to `host`, the embedded app
     * will show a button to ask the host app to show a nav.
     */
    mode?: 'host' | 'default';
    /**
     * Indicates whether the left nav will be initially modal.
     */
    initialModality?: 'modal' | 'hidden';

    /**
     * Type of left nav
     */
    preset?: 'oneDrive' | 'current-site';

    /**
     * Custom commands to insert at the end of the left nav. Will appear before the default set.
     */
    commands?: {
      /**
       * Name to use when notifying the host that the command is being invoked.
       */
      key: string;
      /**
       * Localized string to use for the button text.
       */
      label: string;
      /**
       * Type of action which will be performed when the command is clicked.
       * 'custom': Configured via `commands.custom`.
       */
      action: 'custom' | 'pick' | 'close' | 'browse-this-device';
      /**
       * Name of a Fluent icon to use for the command button.
       */
      icon?: string;
    }[];
  };
  /**
   * The theme to use for the file-picker. Will change the coloring.
   * Note: custom theme objects are expected in addition to the strings below
   * @default 'default': Light theme
   */
  theme?: 'default' | 'dark' | 'lists';
  list?: {
    /**
     * A custom override for the initial list layout.
     */
    layout?: {
      /**
       * Sets the preferred starting layout for the initial content.
       */
      type?: 'details' | 'compact-details' | 'tiles';
    };
    /**
     * Configures scrolling behavior within the Picker.
     */
    scrolling?: {
      enableStickyHeaders?: boolean;
    };
  };
  /**
   * Provides a header title for the Picker.
   */
  title?: string;
  /**
   * Specifies customizations for specific pivots
   */
  pivots?: {
    /**
     * Customize the site pivot
     */
    site?: {
      byPath?: {
        /**
         * Chose the site url to use for this pivot
         * Required to show the site pivot, if undefined
         * the site pivot will not be shown
         */
        web?: string;
      };
    };
  };
};
