import { ComponentType, ReactNode, SyntheticEvent } from "react";
import { EditContextType } from "../editor/client/editContext";
import type { ComponentCommand } from "../editor/commands/componentCommands";
import { Command, CommandData, KeyboardCommand } from "../editor/commands/commands";
import { EditorWarningProps } from "../editor/EditorWarnings";
import { Component, Field, FieldButton, FullItem } from "../editor/pageModel";
import { InsertItemCommand, ItemCommand, ItemCommandData, MoveCopyItemsCommand } from "../editor/commands/itemCommands";
import { User } from "../types";
import { ToolbarGroupConfig } from "../editor/field-types/richtext/types";
import type { ContentTreeIndicatorActionDefinition } from "../editor/tree-indicators/types";
import { WorkspaceDefinition } from "./types/workspace";
import { SidebarDefinition } from "./types/sidebar";
export type NotificationRouteContext = Record<string, unknown>;
export type NotificationRouteDefinition<TContext extends NotificationRouteContext = NotificationRouteContext> = {
    parseContext: (context: unknown) => TContext | null;
    open: (editContext: EditContextType, context: TContext) => Promise<boolean> | boolean;
};
export type RichTextEditorProfile = {
    toolbar: {
        groups: ToolbarGroupConfig[];
    };
};
export type ClientFieldButton = FieldButton & {
    clientAction?: FieldAction;
    visible?: VisibleFunction;
    /** When this returns true, the field action is shown disabled (e.g. missing prerequisite value). */
    isDisabled?: VisibleFunction;
    componentAction?: string;
    isPimaryAction?: boolean;
};
export type FieldAction = ({ editContext, }: FieldActionProps) => Promise<any> | void;
export type FieldActionProps = {
    editContext: EditContextType;
    field: Field;
    event?: SyntheticEvent | globalThis.MouseEvent;
};
export type ManualSelectorDefinition = {
    name: string;
    selector: string;
    availabilitySelector?: string;
    description: string;
    notFoundMessage?: string;
    location?: string;
    isSidebarOnly?: boolean;
    beforeAction?: string;
    afterAction?: string;
};
export type ManualActionProps = {
    editContext: EditContextType;
    selectorDef: ManualSelectorDefinition;
    duration: number;
    runId: string;
    elements: HTMLElement[];
    resolveElements: (selector?: string) => HTMLElement[];
};
export type ManualAction = (props: ManualActionProps) => Promise<any> | void;
export type VariantFieldActionProps = FieldActionProps & {
    variantName?: string;
    variantData?: any;
};
export type VisibleFunction = (context: {
    field: Field;
    variantName?: string;
    variantData?: any;
    rawVariant?: any;
}) => boolean;
export type FieldContextMenuFactory = (field: Field, editContext: EditContextType) => Promise<MenuItem[]> | MenuItem[];
export type RichTextEditorToolbarGroup = {
    marks: RichTextEditorToolbarItem[];
    blocks: RichTextEditorToolbarItem[];
    alignments: RichTextEditorToolbarItem[];
};
export type RichTextEditorToolbarItem = string;
export type EditorClientBuilderProps = {
    configuration: EditorConfiguration;
    buildClient: (configuration: EditorConfiguration) => ReactNode;
    user: User;
};
export type Panel = {
    name: string;
    title: string;
    icon?: string | React.JSX.Element;
    header?: ComponentType;
    content: ReactNode;
    initialSize: number;
    noOverflow?: boolean;
};
export type PanelFactory = (editContext: EditContextType) => Panel;
export type Sidebar = {
    panels: (Panel | PanelFactory)[];
    title?: string;
    icon?: ReactNode;
};
export type ToolbarFactory = (editContext: EditContextType) => ReactNode;
export type EditorView = {
    name: string;
    extends?: string;
    title?: string;
    icon?: string | React.JSX.Element;
    defaultCenterPanelView?: ReactNode;
    menuBar?: ReactNode;
    leftSidebar?: Sidebar;
    rightSidebar?: Sidebar;
    hidden?: boolean;
    toolbarFactory?: ToolbarFactory;
    hideViewSelector?: boolean;
    visible?: (editContext: EditContextType) => boolean;
    beforeClose?: (editContext: EditContextType) => Promise<boolean>;
    headerTitle?: (editContext: EditContextType) => string;
    titlebar?: ReactNode;
    disableAgentsPanel?: boolean;
    hidePinnedSidebars?: boolean;
    /** Optional default width for the sidebar in pixels. Defaults to 350. */
    defaultSidebarWidth?: number;
};
export type SidebarPanelConfig = {
    name: string;
    content: ReactNode;
};
export type MenuItem = {
    id: string;
    label?: string;
    icon?: ReactNode;
    items?: MenuItem[];
    command?: (event: any) => Promise<void>;
    disabled?: boolean;
    separator?: boolean;
    className?: string;
    template?: ReactNode;
};
export type MenuItemGroup = {
    id: string;
    label?: string;
    items: MenuItem[];
};
export interface EditorExtensions {
    [key: string]: unknown;
}
/** Menu types where custom commands can appear */
export type CustomCommandMenuType = "toolbar" | "frameMenu" | "contextMenu";
/** Data returned from backend API for a custom command */
export type CustomCommandData = {
    /** Unique identifier (Sitecore item ID) */
    id: string;
    /** Display label */
    label: string;
    /** Optional SVG icon markup */
    svgIcon?: string;
    /** Command type identifier (e.g., "agent") - must match a registered handler */
    commandType: string;
    /** Sort order for display */
    sortOrder: number;
    /** Type-specific settings (e.g., agent profile, prompt) */
    settings: Record<string, unknown>;
};
/** Context passed to custom command handler functions */
export type CustomCommandContext = {
    editContext: EditContextType;
    event?: React.SyntheticEvent;
    /** For component-scoped commands (frame menu, context menu) */
    components?: Component[];
};
/**
 * Handler for a custom command type, registered in EditorConfiguration.
 * Mirrors the Command<T> interface pattern.
 */
export type CustomCommandHandler = {
    /** Unique command type identifier (e.g., "agent") */
    type: string;
    /** Execute the command - mirrors Command<T>.execute */
    execute: (command: CustomCommandData, context: CustomCommandContext) => Promise<void>;
    /** Determine if disabled - mirrors Command<T>.disabled */
    disabled: (command: CustomCommandData, context: CustomCommandContext) => boolean;
    /** Optional: render custom icon (overrides backend svgIcon) */
    renderIcon?: (command: CustomCommandData) => ReactNode;
};
/**
 * Common props interface for agent dialog inline components.
 * All dialog components receive these standard props plus their specific parameters.
 */
export interface AgentDialogComponentProps<TParams = unknown, TResult = unknown> {
    /** Called when the dialog completes with a result (or null if empty) */
    onClose: (result: TResult | null) => void;
    /** Called when the user cancels the dialog */
    onCancel: () => void;
    /** Optional title for the dialog */
    title?: string;
    /** Optional description/instructions for the dialog */
    description?: string;
    /** Dialog-specific parameters from the backend */
    parameters: TParams;
}
/**
 * Registration entry for an agent dialog component.
 * Maps a dialog type string (from backend) to a React component.
 */
export interface AgentDialogComponentRegistration {
    /** Dialog type identifier (e.g., "component-type-selector", "questionnaire") */
    dialogType: string;
    /** React component that renders this dialog type */
    component: ComponentType<AgentDialogComponentProps<any, any>>;
}
export type ComponentCommandProvider = (components: Component[], editContext: EditContextType) => Promise<ComponentCommand[]> | ComponentCommand[];
export type CommandTemplateRegistration = {
    commandId: string;
    optionName?: string;
    parentPathPrefix?: string;
};
export type EditorConfiguration = {
    extensions: EditorExtensions;
    commands: {
        renameItem: ItemCommand;
        deleteItem: ItemCommand;
        insertItem: InsertItemCommand;
        allItemCommands: Command<ItemCommandData>[];
        keyboardCommands: KeyboardCommand<any>[];
        reviewcommands: Command<CommandData>[];
        moveItems: MoveCopyItemsCommand;
        copyItems: MoveCopyItemsCommand;
        [key: string]: ItemCommand | ItemCommand[] | MoveCopyItemsCommand | InsertItemCommand | Command<any>;
    };
    events: {
        onUnauthorized?: () => void;
    };
    editorWarnings: ComponentType<EditorWarningProps>[];
    fieldTypes: {
        [key: string]: FieldTypeConfiguration;
    };
    outline: {
        width: number;
    };
    debounceFieldEditsInterval: number;
    devices: Device[];
    forceFullscreen?: boolean;
    /**
     * When false, AI affordances such as the field "AI Edit" context menu are hidden.
     * Set by configureForLicense; omitted means not gated (e.g. configure() without license filter).
     */
    hasAiLicense?: boolean;
    editor: {
        defaultPanelSizes: [number, number];
        dialogs: {
            newPage: {
                expandTreeNode?: string;
            };
        };
        /** @deprecated Use workspaces and sidebars instead */
        views?: EditorView[];
        /** @deprecated Use defaultOpenSidebars instead */
        defaultPinnedViews?: string[];
        /** Workspace definitions - fundamentally different UI experiences */
        workspaces: WorkspaceDefinition[];
        /** Sidebar definitions - panels for the Editor workspace */
        sidebars: SidebarDefinition[];
        /** Default workspace to show on startup */
        defaultWorkspace?: string;
        /** Default sidebars to open in the Editor workspace */
        defaultOpenSidebars?: string[];
        /** Optional config-driven actions for manual locator buttons. */
        manualActions?: Record<string, ManualAction>;
        itemActionsMenu?: {
            itemsFactory: (editContext: EditContextType) => MenuItemGroup[];
        };
        mainNavigation?: (MenuItem | Command<any>)[];
        embedded?: boolean;
        contentTree: {
            indicatorActions?: Record<string, ContentTreeIndicatorActionDefinition>;
            contextMenu: {
                factory: (props: {
                    items: FullItem[];
                    editContext: EditContextType;
                    commandCallback?: (command: ItemCommand, result: any) => void;
                }) => Promise<MenuItem[] | undefined>;
            };
        };
        /** Registered agent dialog components for inline UI dialogs */
        agentDialogs?: AgentDialogComponentRegistration[];
        /** Notification type to navigation mapping */
        notificationRoutes?: Record<string, NotificationRouteDefinition<any>>;
    };
    settings: {
        groups: {
            title: string;
            icon: ReactNode;
            panels: SettingsPanel[];
        }[];
    };
    statusChecks?: StatusCheck[];
    /** Custom commands configuration - extensible command system */
    customCommands?: {
        /** Registered handlers for command types (e.g., "agent") */
        handlers: CustomCommandHandler[];
    };
    commandTemplates?: {
        /** Template-folder command templates resolved client-side by insert option typeId */
        byTypeId: Record<string, CommandTemplateRegistration>;
    };
    componentCommands?: {
        providers: ComponentCommandProvider[];
    };
    tours: {
        default: Tour;
        preview: Tour;
    };
    activeTour: string;
    [key: string]: any;
};
export type Tour = {
    getSteps: (params: GetEditorTourStepsParams) => Record<string, TourStep>;
};
export type SettingsPanel = {
    id: string;
    title: string;
    subtitle?: string;
    icon?: ReactNode;
    content: ReactNode;
};
export type StatusCheckSeverity = "error" | "warning" | "info";
export type StatusCheckResult = {
    id: string;
    title: string;
    description: string;
    severity: StatusCheckSeverity;
    /** Panel ID to navigate to (e.g., "ai-providers") */
    targetPanel?: string;
    /** Optional hash for Setup wizard steps (e.g., "#database") */
    targetHash?: string;
    /** Button label (defaults to "Fix") */
    actionLabel?: string;
};
export type StatusCheck = {
    /** Unique identifier for this check */
    id: string;
    /** Display name for loading state */
    name: string;
    /** If true, this check runs at startup and blocks the app if it fails */
    isBlocking?: boolean;
    /** The check function - returns issues found, or empty array if all good */
    check: () => Promise<StatusCheckResult[]>;
};
export type Device = {
    name: string;
    width: number | undefined;
    height: number | undefined;
};
export type FieldTypeConfiguration = {
    editor: React.ComponentType<any>;
    buttons?: FieldButton[];
    variantButtons?: FieldButton[];
    custom?: any;
    contextMenuFactory?: FieldContextMenuFactory;
    paste?: FieldTypePasteConfig;
    /** Enable AI image editing for picture/image field types (defaults to false) */
    aiImageEdit?: boolean;
};
export type FieldTypePasteConfig = {
    enabled?: (field: Field) => boolean;
    /** A higher-level kind that implies validation/transform behavior */
    kind?: {
        type: "text";
    } | {
        type: "guid";
    } | {
        type: "guid-list";
        separator?: string;
    };
    /** Return true if clipboard content is acceptable for this field type */
    isValid?: (clipboardText: string) => boolean;
    /** Optionally transform clipboard text into the value to store */
    transform?: (clipboardText: string, field: Field) => string | undefined | null;
    /** Whether to hide the paste button if the clipboard is invalid/empty. Defaults to true. */
    hideIfInvalidClipboard?: boolean;
    /** Where to write the value when pasting. Defaults to 'value'. */
    target?: "value" | "rawValue";
};
export type TourButton = {
    label: ReactNode;
    onClick: () => void;
    className?: string;
};
export type TourStep = {
    title?: ReactNode;
    description?: ReactNode;
    focusElement?: string;
    extendFocus?: number;
    prepareAction?: () => Promise<void>;
    action?: () => Promise<void>;
    bubblePosition?: "left" | "right" | "bottom" | "top" | "top-right" | "bottom-right" | "top-left";
    /** When the bubble sits to the left/right of the focus, align it to the top or vertical center of the focus rect. */
    bubbleVerticalAnchor?: "top" | "center";
    flipArrow?: boolean;
    waitForUserInput?: () => Promise<string | void>;
    buttons?: TourButton[];
    nextStep?: string;
    waitForElement?: string;
    getPointTo?: () => DOMRect | undefined;
    pointToElement?: string;
    skipIf?: (configuration: EditorConfiguration) => boolean;
    /** Block page/shell scroll; optional allowSelector keeps scrolling inside that element. */
    lockScroll?: boolean | {
        allowSelector?: string;
    };
};
export type GetEditorTourStepsParams = {
    editContext: EditContextType;
    nextStep: (stepId: string) => void;
    stopTour: () => void;
    waitForElement: (selector: string, timeout?: number) => Promise<DOMRect | undefined>;
    waitForElementToDisappear: (selector: string) => Promise<void>;
    setFocusRect: (rect: DOMRect) => void;
    delay: (ms: number) => Promise<void>;
    waitForInput: (selector: string, minNumberOfCharacters: number) => Promise<void>;
    simulateTyping: (element: HTMLInputElement | HTMLTextAreaElement, text: string, interval?: number) => Promise<void>;
};
export * from "./types/workspace";
export * from "./types/sidebar";
