/**
 * Copyright (c) 2024 Lark Technologies Pte. Ltd.
 * 
 * Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted,provided that the above copyright notice and this permission notice appear in all copies.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE
 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
 * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
 */
import { CSSProperties } from 'react';
import { Dispatch } from 'react';
import { ForwardedRef } from 'react';
import { ForwardRefExoticComponent } from 'react';
import { ReactElement } from 'react';
import { RefAttributes } from 'react';
import { RefObject } from 'react';
import { RichTextEditorContent } from '@lark-project/js-sdk';
import { RichTextEditorOptions } from '@lark-project/js-sdk';
import { SetStateAction } from 'react';
import { User } from '@lark-project/js-sdk';
import { WorkItemFinderOptions } from '@lark-project/js-sdk';

/**
 * [基础组件] DatePicker
 */
export declare function DatePicker(props: IDatePickerProps): ReactElement;

export declare namespace DatePicker {
    var RangePicker: typeof DateRangePicker;
}

/**
 * [基础组件] RangePicker
 */
declare function DateRangePicker(props: IRangePickerProps): ReactElement;

declare type DateValue = Date | string | number | undefined;

export declare type DisabledDateOptions = {
    rangeStart?: string;
    rangeEnd?: string;
    rangeInputFocus?: 'rangeStart' | 'rangeEnd' | false;
};

/**
 * dom 通用属性
 */
declare interface IBaseDOMProps {
    /**
     * 类名
     */
    className?: string;
    /**
     * 样式
     */
    style?: CSSProperties;
}

declare interface IBaseEndpointProps {
    serviceType: string;
    refer?: {
        handler?: ITriggerEndpointHandler;
    };
    /**
     * init 时触发回调
     *
     * 为了不忘记要有return销毁，这里类型上强制有返回函数
     * @returns 组件销毁时会调用 return 的函数，用于销毁一些副作用，函数不会响应引用变化
     */
    onInit?: (params: {
        handler: ITriggerEndpointHandler;
    }) => () => void;
    /**
     * 是否作为组件 child 使用，为 true 时不计入组件总数
     */
    asChild?: boolean;
    /**
     * 是否需要初始化与 host 的通信
     * false 时不初始化不发送 init 消息，适用于 trigger 渲染不依赖 host 的场景
     */
    needInit?: boolean;
}

/**
 * 对标基础组件库 api 设置
 */
declare interface IBasePopoverProps {
    /**
     * 自定义 trigger dom 元素
     *
     * 满足与semi Popover 一致的约定，以下描述引用自semi：
     *
     * Popover 需要将 DOM 事件监听器应用到 children 中，如果子元素是自定义的组件，你需要确保它能将属性传递至底层的 DOM 元素
     *
     * 同时为了计算弹出层的定位，需要获取到 children 的真实 DOM 元素，因此 Popover 支持如下类型的 children
     *
     * 1. Class Component，不强制绑定ref，但需要确保 props 可被透传至真实的 DOM 节点上
     * 2. 使用 forwardRef 包裹后的函数式组件，将 props 与 ref 透传到 children 内真实的 DOM 节点上
     * 3. 真实 DOM 节点, 如 span，div，p...
     */
    children?: ReactElement;
    /**
     * 支持设置浮层弹出方向
     */
    position?: 'left' | 'top' | 'topLeft' | 'topRight' | 'leftTop' | 'leftBottom' | 'right' | 'rightTop' | 'rightBottom' | 'bottom' | 'bottomLeft' | 'bottomRight';
}

declare interface IBaseSelectProps {
    /**
     * 选择框默认文字
     */
    placeholder?: string;
    /**
     * 是否禁用
     */
    disabled?: boolean;
    /**
     * 多选模式下，已选项超出 maxTagCount 时，后续选项会被渲染成+N 的形式
     */
    maxTagCount?: number;
    /**
     * 是否多选
     */
    multiple?: boolean;
    /**
     * 是否展示清除按钮
     */
    showClear?: boolean;
}

declare interface IBaseUserTagProps extends IBaseDOMProps, Pick<IBasePopoverProps, 'children'> {
    larkUserId?: string;
    /**
     * 用户 id
     */
    userId?: string;
    name?: string;
    avatar?: string;
    /**
     * 是否禁用，禁用将不会弹出用户卡片
     */
    disabled?: boolean;
    /**
     * 是否可关闭
     */
    closable?: boolean;
    onClose?: (tagChildren: React.ReactNode, event: React.MouseEvent<HTMLElement>, tagKey: string | number) => void;
}

export declare interface IDatePickerProps extends Pick<IDateTriggerProps, 'className' | 'style' | 'showClear' | 'disabled' | 'inputReadOnly' | 'onClear' | 'placeholder'> {
    showTime?: boolean;
    format?: string;
    presets?: PresetItem[];
    weekStartsOn?: number;
    defaultValue?: DateValue;
    value?: DateValue;
    onChange?: (date: Date | undefined, dateStr: string | undefined) => void;
    onPresetClick?: (preset: PresetItem) => void;
    onFocus?: () => void;
    onBlur?: () => void;
    disabledDate?: (date: Date) => boolean;
}

declare interface IDateTriggerProps extends IBaseDOMProps {
    type: 'date' | 'dateTime' | 'month';
    showClear?: boolean;
    inputReadOnly?: boolean;
    disabled?: boolean;
    isFocused?: boolean;
    value?: string;
    onChange?: (value: string) => void;
    onClear?: () => void;
    onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
    placeholder?: string;
}

export declare interface IEditor {
    setValue: (val: Pick<RichTextEditorContent, 'doc'>) => void;
}

declare type IEndpointDispatch = <DispatchContext extends IEndpointPayload>(context: DispatchContext, cb?: (ret: any) => void) => Promise<void>;

declare interface IEndpointEvent<Context = any> {
    payload: Context;
}

declare interface IEndpointMsgPayload<Context extends IEndpointPayload<any> = IEndpointPayload<any>> {
    endpointId: string;
    serviceType: string;
    payload: Context;
}

declare type IEndpointOnMessage = <Context = Record<string, any>, K extends keyof Context = keyof Context>(type: K, cb: (payload?: Context[K], msg?: IEndpointMsgPayload<IEndpointPayload<Context, K>>) => void) => () => void;

declare interface IEndpointPayload<Context = Record<string, any>, K extends keyof Context = keyof Context> {
    type: K;
    sessionId?: string;
    payload?: Context[K];
}

/**
 * 通用错误表达结构
 */
declare interface IError {
    /**
     * 错误码，一般非0表示存在错误
     */
    c: number;
    /**
     * 当有错误时，提供对应的错误描述信息
     */
    m: string;
}

declare interface IInnerInfo {
    type: PopType;
}

export declare function init(): Promise<void>;

export declare interface IPopoverContent {
    Provider: (props: IPopoverContentProviderProps) => React.ReactElement;
    Consumer: React.Consumer<IPopoverContentType>;
    useContext: <T extends Record<string, any> = Record<string, any>>() => IPopoverContentType<T>;
}

declare interface IPopoverContentProviderProps {
    children: React.ReactNode;
}

declare interface IPopoverContentType<T extends Record<string, any> = Record<string, any>> {
    context: T;
    ref: React.MutableRefObject<any>;
}

export declare interface IPopoverProps extends IBasePopoverProps, Pick<IBaseDOMProps, 'style'> {
    /**
     * 触发方式
     */
    trigger?: 'hover' | 'click' | 'custom';
    /**
     * 如果只需要展示普通文本，直接给定 content 字符串即可
     */
    content?: string;
    /**
     * 自定义 entry 函数名，与插件在入口导出的自定义函数名匹配
     */
    entry?: string;
    /**
     * 指定 entry 时，允许传入自定义参数。
     *
     * 组件会将此参数携带给插件自定义 entry 函数的入参 props.context。
     *
     * 建议使用平面对象，不支持函数，proxy，等非常规数据。
     */
    context?: any;
    /**
     * 弹出层展示/隐藏时触发的回调
     */
    onVisibleChange?: (visible: boolean) => void;
    /**
     * 弹出层是否可见，配合trigger = 'custom' 时使用
     */
    visible?: boolean;
    /**
     * 当弹出层处于展示状态，点击非Children、非浮层内部区域时的回调（仅trigger为custom、click时有效）
     */
    onClickOutSide?: () => void;
}

export declare interface IRangePickerProps extends Pick<IDatePickerProps, 'className' | 'style' | 'showClear' | 'disabled' | 'inputReadOnly' | 'onClear' | 'showTime' | 'weekStartsOn' | 'format' | 'presets' | 'disabledDate' | 'onPresetClick' | 'onFocus' | 'onBlur'>, Pick<IRangeTriggerProps, 'rangeSeparator' | 'placeholder'> {
    defaultValue?: Date[] | string[] | number[];
    value?: Date[] | string[] | number[];
    onChange?: (date: Date[], dateStr: string[]) => void;
    disabledDate?: (date: Date, options?: DisabledDateOptions) => boolean;
}

declare interface IRangeTriggerProps extends IBaseDOMProps {
    type?: 'dateRange' | 'dateTimeRange' | 'monthRange';
    placeholder?: string[];
    startValue?: string;
    endValue?: string;
    onStartValueChange?: (value: string) => void;
    onEndValueChange?: (value: string) => void;
    inputReadOnly?: boolean;
    disabled?: boolean;
    showClear?: boolean;
    rangeSeparator?: string;
    rangeInputFocus: RangeFocusType;
    setRangeInputFocus: Dispatch<SetStateAction<RangeFocusType>>;
    onClear?: () => void;
    onClick?: () => void;
    rangeInputStartRef?: RefObject<HTMLInputElement>;
    rangeInputEndRef?: RefObject<HTMLInputElement>;
}

declare interface IRect {
    height: number;
    bottom: number;
    left: number;
    right: number;
    top: number;
    width: number;
    x: number;
    y: number;
}

export declare interface IRichTextEditorInlineProps extends IBaseDOMProps, Pick<RichTextEditorOptions, 'imageUpload'> {
    /**
     * 空间 id，用于 doc2DocHTML 等功能
     */
    spaceId: string;
    /**
     * 富文本内容
     * doc 是富文本内容必须数据
     * doc_html 是快速上屏数据，请确保表达内容与 doc 一致
     */
    defaultValue?: Pick<RichTextEditorContent, 'doc' | 'doc_html'>;
    /**
     * 编辑器失焦（点击外部）时的回调
     */
    onSubmit?: (value: RichTextEditorContent) => void;
    /**
     * 占位文本
     */
    placeholder?: string;
    /**
     * 是否自动聚焦
     */
    autoFocus?: boolean;
    /**
     * 编辑区域最大高度(px)，超出滚动
     */
    maxHeight?: number;
    /**
     * @人 mention 节点的渲染样式开关
     * - true：头像 + 灰底胶囊样式（与 inline 模式当前实现一致）
     * - false（默认）：仅蓝色 @姓名 文字（与 Popover 模式样式一致）
     *
     * 由 editor-kit PCMention 的 showUserAvatar 选项控制，
     * 切换的是 mention 节点本身的内联样式，无 CSS 覆盖能力，
     * 必须通过此开关传入。
     */
    mentionShowAvatar?: boolean;
}

export declare interface IRichTextEditorPopoverProps extends IBaseDOMProps, IBasePopoverProps, Pick<ITriggerControllerProps, 'disabled' | 'trigger' | 'visible' | 'onVisibleChange' | 'onClickOutSide'>, Pick<RichTextEditorOptions, 'imageUpload' | 'autoFocus'> {
    /**
     * 空间 id，用于url、图片、mention等功能
     */
    spaceId: string;
    /**
     * 富文本内容
     * doc 是富文本内容必须数据
     * doc_html 是快速上屏数据，请确保表达内容与doc一致
     */
    defaultValue?: Pick<RichTextEditorContent, 'doc' | 'doc_html'>;
    /**
     * 弹出层宽度
     */
    contentWidth?: CSSProperties['width'];
    /**
     * 富文本触发 onClickOutSide 时会自动触发 onSubmit 回调
     * @param value
     * @returns
     */
    onSubmit?: (value: RichTextEditorContent) => void;
}

export declare interface IRichTextEditorProps extends Pick<IRichTextEditorPopoverProps, 'imageUpload' | 'spaceId' | 'defaultValue'> {
    /**
     * 默认值 true ，如果想预览富文本请主动给组件加上editable={false}
     */
    editable?: boolean;
    /**
     * 编辑类型，默认inline，popover为弹出式编辑
     */
    editType?: 'inline' | 'popover';
    /**
     * 提交回调
     * - inline 模式：编辑器退出编辑（点击外部/失焦）时触发
     * - popover 模式：onClickOutSide 时触发
     */
    onSubmit?: (value: RichTextEditorContent) => void;
    /**
     * editType 为 popover 时，对 popover 生效的 props
     */
    editPopoverProps?: Omit<IRichTextEditorPopoverProps, 'imageUpload' | 'spaceId' | 'defaultValue' | 'onSubmit'> & {
        ref?: ForwardedRef<IEditor | undefined>;
        /**
         * @deprecated 请使用 IRichTextEditorProps.onSubmit
         */
        onSubmit?: (value: RichTextEditorContent) => void;
    };
    /**
     * editType 为 inline 时，对 inline 编辑器生效的 props
     */
    editInlineProps?: Pick<IRichTextEditorInlineProps, 'placeholder' | 'maxHeight'>;
}

export declare interface ISelectOption<DATA extends Record<string, any> = Record<string, any>> {
    value: string;
    label: string;
    disabled?: boolean;
    data?: DATA;
}

export declare interface ISelectOptionsProps<DATA extends Record<string, any>> {
    className?: string;
    style?: React.CSSProperties;
    emptyContent?: ReactElement | string;
    renderOptionItem?: (option: ISelectOption<DATA>) => React.ReactNode;
}

export declare interface ISelectProps<DATA extends Record<string, any> = Record<string, any>> extends Pick<ISelectTriggerProps<DATA>, 'optionList' | 'filter' | 'onSearch' | 'onClear' | 'renderSelectedItem' | 'className' | 'style' | 'multiple' | 'placeholder' | 'disabled' | 'maxTagCount' | 'showClear' | 'value' | 'onChange'> {
    /**
     * 自定义 entry 函数名，与插件在入口导出的自定义函数名匹配
     */
    entry?: string;
}

declare interface ISelectTriggerProps<DATA extends Record<string, any>> extends IBaseSelectProps, IBaseDOMProps {
    selectRef?: React.RefObject<any>;
    /**
     * select 选项列表
     */
    optionList: ISelectOption<DATA>[];
    /**
     * 选中的选项
     */
    value?: string | string[] | undefined;
    /**
     * 选中的选项
     */
    filter?: boolean;
    /**
     * input 输入框内容发生改变时回调函数
     */
    onSearch?: (value: string) => void;
    /**
     * 是否展示加载动画
     */
    /**
     * 弹出位置
     */
    /**
     * 变化时回调函数
     */
    onChange?: (value: string | string[] | undefined, selectedOptions: ISelectOption<DATA> | ISelectOption<DATA>[] | undefined) => void;
    /**
     * 点击清除按钮后的回调
     */
    onClear?: () => void;
    /**
     * 点击 Trigger 后的回调
     */
    onClick?: () => void;
    /**
     * 自定义渲染选中项
     */
    renderSelectedItem?: (optionNode: ISelectOption<DATA>) => React.ReactElement | {
        isRenderInTag: boolean;
        content: React.ReactElement;
    };
}

declare interface ITargetListenerMap {
    bounding: IEndpointEvent<{
        rect: IRect;
    }>;
    clickOutSide: IEndpointEvent<undefined>;
    hover: IEndpointEvent<{
        hovering: boolean;
    }>;
    viewportVisible: IEndpointEvent<{
        visible: boolean;
    }>;
}

declare interface ITriggerControllerProps<T extends Record<string, any> = Record<string, any>> extends IBaseEndpointProps, Pick<IBasePopoverProps, 'children'> {
    /**
     * 触发方式
     */
    trigger?: 'hover' | 'click' | 'custom';
    /**
     * 弹出层是否可见，配合trigger = 'custom' 时使用
     */
    visible?: boolean;
    /**
     * 弹出层展示/隐藏时触发的回调
     */
    onVisibleChange?: (visible: boolean) => void;
    /**
     * 当弹出层处于展示状态，点击非Children、非浮层内部区域时的回调（仅trigger为custom、click时有效）
     */
    onClickOutSide?: () => void;
    mouseEnterDelay?: number;
    mouseLeaveDelay?: number;
    openPayload?: {
        popoverProps?: Omit<IBasePopoverProps, 'children'> & IBaseDOMProps & {
            sizeLimit?: boolean;
        };
    } & Record<string, any>;
    disabled?: boolean;
    contentRef?: React.MutableRefObject<{
        popup?: Record<string, any>;
    }>;
    context?: T;
    innerInfo?: IInnerInfo;
    startTiming?: RefObject<number>;
}

declare interface ITriggerEndpointHandler {
    destroy: () => void;
    open: <Context extends Record<string, any>>(context?: Context, option?: {
        noBounding?: boolean;
    }) => Promise<void>;
    close: () => Promise<void>;
    dispatch: IEndpointDispatch;
    onMessage: IEndpointOnMessage;
    addTargetListener: <K extends keyof ITargetListenerMap>(type: K, handler: (payload: ITargetListenerMap[K]) => void) => () => void;
    define: (funcMap: Record<string, () => (...args: any[]) => any>) => () => void;
    onDefine: (cb?: (funcList: Record<string, (...args: any[]) => any>) => void) => () => void;
}

export declare interface IUserSelectProps extends IBaseDOMProps, IBaseSelectProps {
    /**
     * 当前选中的用户 ids
     */
    userIds?: string[];
    /**
     * userIds 变化时回调函数
     * @param userIds
     * @param users
     * @returns
     */
    onChange?: (userIds: string[], users: User[]) => void;
    /**
     * 自定义选项范围，限制可选的 userIds 范围
     */
    optionIds?: string[];
    /**
     * 禁用的 userIds，不可选择 / 反选
     */
    disabledIds?: string[];
    /**
     * 禁止弹出用户卡片
     */
    userCardDisabled?: boolean;
    /**
     * 空间标识
     * 1. 影响用户搜索范围：
     *
     *   1.1 非企业互联租户，无论是否提供 spaceId，搜索全租户
     *
     *   1.2 企业互联租户
     *
     *     1.2.1 提供 spaceId:
     *       a. spaceId 是开放空间：搜索当前登录租户 + 协作租户开放名单
     *       b. spaceId 不是开放空间：只搜索当前登录租户
     *
     *     1.2.2 不提供 spaceId: 搜索当前登录租户
     * 2. 影响推荐用户列表:
     *
     *   2.1 提供 spaceId: 默认推荐用户列表对不同空间有区别
     *
     *   2.2 未提供 spaceId: 默认推荐用户列表对不同空间无区别
     */
    spaceId?: string;
}

export declare interface IUserTagProps extends IBaseDOMProps, Pick<IBaseUserTagProps, 'userId' | 'closable' | 'disabled' | 'name' | 'avatar'> {
    /**
     * 关闭回调
     * @returns
     */
    onClose?: () => void;
}

export declare interface IWorkItemFinderProps extends IBaseDOMProps, IBasePopoverProps, Omit<WorkItemFinderOptions, 'title'> {
    /**
     * 是否禁用，禁用状态下不能打开配置界面
     */
    disabled?: boolean;
    /**
     * 修改配置触发
     * @param params total：筛选条件数量
     * @returns
     */
    onChange?: (params: {
        total: number;
    }) => void;
    /**
     * 保存提交
     * @param params searchId 筛选条件id
     * @returns
     */
    onSubmit?: (params: {
        searchId: string;
        searchGroup?: any;
    }) => void;
    /**
     * 非阻塞异常，以下情况会触发此回调：
     * 1. { c: 1, m: 'searchId not match spaceId or workObjectId' }
     * @param err
     * @returns
     */
    onValidateError?: (err: IError) => void;
    /**
     * 阻塞异常，比如保存失败
     * @param err
     * @returns
     */
    onError?: (err: IError) => void;
}

declare function OriginSelectOptions<DATA extends Record<string, any> = Record<string, any>>(props: ISelectOptionsProps<DATA>): ReactElement;

/**
 * [基础组件] Popover
 */
export declare const Popover: PopoverComponent;

declare interface PopoverComponent extends ForwardRefExoticComponent<IPopoverProps & RefAttributes<{
    popup?: Record<string, any>;
}>> {
    PopoverContent: IPopoverContent;
}

declare type PopType = 'Popover' | 'Select';

/**
 * @deprecated PopupContentContext is deprecated. Please use Popover.PopoverContent instead.
 */
export declare const PopupContentContext: IPopoverContent;

export declare type PresetItem = {
    text?: string;
    start?: Date;
    end?: Date;
};

declare type RangeFocusType = 'rangeStart' | 'rangeEnd' | '';

/**
 * [业务组件] RichTextEditor
 *
 * 富文本编辑器
 */
export declare function RichTextEditor({ spaceId, defaultValue, editable, imageUpload, editType, onSubmit, editPopoverProps, editInlineProps, }: IRichTextEditorProps): ReactElement;

/**
 * [基础组件] Select
 */
export declare function Select<DATA extends Record<string, any> = Record<string, any>>(props: ISelectProps<DATA>): ReactElement;

export declare namespace Select {
    var SelectOptions: typeof OriginSelectOptions;
}

/**
 * [业务组件] UserSelect
 *
 * 用户选择
 */
export declare function UserSelect({ className, style, multiple, placeholder, showClear, disabled, maxTagCount, spaceId, userIds: _userIds, onChange, optionIds, disabledIds, userCardDisabled, }: IUserSelectProps): ReactElement;

/**
 * [业务组件] UserTag
 *
 * 用户标签，hover 出用户卡片
 */
export declare function UserTag({ className, style, userId, name, avatar, closable, onClose, disabled }: IUserTagProps): ReactElement;

/**
 * [业务组件] 工作项筛选器
 */
export declare function WorkItemFinder({ className, style, children, disabled, onChange, onSubmit, onValidateError, onError, searchId, position, spaceId, workObjectId, backfill, forceCreateNewSearchId, }: IWorkItemFinderProps): ReactElement;

export { }
