import { CSSProperties, ReactElement, ReactNode } from 'react';
import { AiMarkWithTooltipOrPopoverProps, LayoutUtilProps, Size } from '../../../types';
import { OptionContent } from '../../../internal/types/optionContent';
import { MultiSelectFieldChipProps } from '../../../components/MultiSelectField/types';
/**
 * Partial chip props that can be returned from the TreeSelectField `getChipProps` callback.
 * Supports `icon` or `avatar` (mutually exclusive) and all other chip props as optional overrides.
 * Core props (`label`, `onClose`, `className`, `title`, `size`) are managed by the component.
 */
export type TreeSelectFieldChipProps = MultiSelectFieldChipProps;
/**
 * Rich content configuration for a TreeSelectField option row.
 * Controls the avatar, icon, description, and chip display within an option.
 */
export type TreeSelectFieldOptionContent = OptionContent;
/**
 * A node in the tree structure.
 * @property id - Unique identifier for the node.
 * @property label - Display text for the node.
 * @property searchText - Additional text to match during search, beyond label.
 * @property disabled - Whether the node is disabled for selection.
 * @property extra - Pass-through data for consumer convenience.
 * @property children - Child nodes. undefined=leaf, []=empty branch, [...]=branch, null=unloaded (lazy).
 * @property childCount - Server-provided count, optionally displayed on branch nodes.
 * @property path - Optional ancestor ids, root→parent. Selection-ancestry
 *   metadata, primarily meaningful on value objects: when a selected node lives
 *   under branches that aren't currently loaded, `path` lets the field show the
 *   correct ancestor check states without a parent-of lookup. The field emits
 *   it on selections whose ancestry it knows, and reads it from incoming value
 *   so a persisted-then-restored selection resolves exactly. Not a structural
 *   tree attribute — omit it on `loadOptions` results.
 */
export type TreeSelectFieldNode = {
    id: string | number;
    label: string;
    searchText?: string;
    disabled?: boolean;
    extra?: Record<string, unknown>;
    content?: TreeSelectFieldOptionContent;
    children?: TreeSelectFieldNode[] | null;
    childCount?: number;
    path?: (string | number)[];
};
/**
 * The value shape stored in the value array. Intentionally slim — just enough to render chips and identify the node.
 * @property id - The node's unique identifier.
 * @property label - The node's display text.
 * @property extra - Pass-through data from the node.
 * @property path - Optional ancestor ids, root→parent. See {@link TreeSelectFieldNode.path}.
 */
export type TreeSelectFieldValue = Pick<TreeSelectFieldNode, "id" | "label" | "extra" | "path">;
/**
 * Controls which nodes are selectable and how the value array is shaped.
 * - "ALL" — any node selectable, all checked nodes in value
 * - "BRANCH_PRIORITY" — any node selectable, branches replace leaves when fully checked
 * - "BRANCH_ONLY" — only branches selectable, leaves visible but inert
 * - "LEAF_PRIORITY" — only leaves selectable (branches expand), leaves + childless branches in value
 * - "LEAF_ONLY" — only leaves selectable (branches expand), strictly leaves in value
 */
export type TreeSelectFieldValueConsistsOf = "ALL" | "BRANCH_PRIORITY" | "BRANCH_ONLY" | "LEAF_PRIORITY" | "LEAF_ONLY";
/**
 * Imperative handle for the TreeSelectField component.
 * @property clearCache - Clears the options cache.
 * @property invalidate - Clears the cache and triggers a fresh options load.
 * @property expandAll - Expands all tree nodes.
 * @property collapseAll - Collapses all tree nodes.
 */
export type TreeSelectFieldHandle = {
    clearCache: () => void;
    invalidate: () => void;
    expandAll: () => void;
    collapseAll: () => void;
};
/**
 * Props for the TreeSelectField component.
 * @property label - Required label for accessibility.
 * @property value - Controlled value array. Always an array, even in single-select mode.
 * @property onSelectedOptionsChange - Callback when selection changes.
 * @property loadOptions - Async function to load tree nodes. Called with parentNode for lazy branch loading.
 * @property selectionMode - "single": one node at a time. "independent": no cascade. "linked" (default): parent-child cascade.
 * @property valueConsistsOf - Controls which nodes are selectable and how the value is shaped.
 * @property defaultExpandLevel - Initial expand depth. 0=collapsed, Infinity=all.
 * @extends LayoutUtilProps
 */
export type TreeSelectFieldProps = {
    id?: string;
    label: string;
    labelNode?: ReactNode;
    hideLabel?: boolean;
    placeholder?: string;
    size?: Extract<Size, "small" | "medium" | "large">;
    displayMenuAs?: "auto" | "popover" | "dialog";
    error?: boolean | string | string[] | ReactElement;
    hint?: ReactElement | string;
    /** Additional information to display in a tooltip next to the label. */
    moreInfo?: ReactNode;
    /**
     * AI mark configuration to display next to the label.
     * Can be a boolean to show a simple AI mark, or an object with tooltip/popover configuration.
     */
    labelAiMark?: AiMarkWithTooltipOrPopoverProps["aiMark"];
    description?: ReactElement | string;
    warning?: string | string[];
    required?: boolean;
    disabled?: boolean;
    readOnly?: boolean;
    prefix?: string | ReactElement;
    suffix?: string | ReactElement;
    className?: string;
    style?: CSSProperties;
    disableSearch?: boolean;
    debounceMs?: number;
    searchValue?: string;
    onSearchChange?: (v: string) => void;
    singleRow?: boolean;
    maxChips?: number;
    /**
     * Callback to customize chip props for each selected option.
     * Allows customizing chip appearance (color, icon, avatar, etc.) per option.
     * Core props (label, onClose, className, title, size) are managed by the component and excluded from this type.
     * @param value - The selected value the chip represents
     * @returns Partial chip props to merge onto the chip
     */
    getChipProps?: (value: TreeSelectFieldValue) => TreeSelectFieldChipProps;
    virtualize?: boolean;
    value: TreeSelectFieldValue[];
    onSelectedOptionsChange: (nodes: TreeSelectFieldValue[]) => void;
    selectionMode?: "single" | "independent" | "linked";
    valueConsistsOf?: TreeSelectFieldValueConsistsOf;
    defaultExpandLevel?: number;
    expandedIds?: Set<string | number>;
    onExpandedIdsChange?: (ids: Set<string | number>) => void;
    loadOptions: (searchValue: string, parentNode?: TreeSelectFieldNode) => TreeSelectFieldNode[] | Promise<TreeSelectFieldNode[]>;
    cache?: {
        enabled?: boolean;
        maxSize?: number;
    };
    initialLoad?: "auto" | "immediate" | "open";
} & LayoutUtilProps;
