import { ComputedRef, DefineComponent, Directive, Ref } from 'vue';
import type { Placement } from '@popperjs/core';

export type FieldSize = 'large' | 'default' | 'small';

export interface AutocompleteProps {
  modelValue?: string;
  placeholder?: string;
  clearable?: boolean;
  disabled?: boolean;
  triggerOnFocus?: boolean;
  valueKey?: string;
  debounce?: number;
  size?: FieldSize;
  placement?: 'top' | 'top-start' | 'top-end' | 'bottom' | 'bottom-start' | 'bottom-end';
  fetchSuggestions?: (queryString: string, callback: (data: any[]) => any) => void;
}

export interface BadgeProps {
  value?: string | number;
  type?: 'primary' | 'success' | 'warning' | 'danger' | 'info';
  max?: number;
  isDot?: boolean;
  hidden?: boolean;
}

export interface ButtonProps {
  type?: string;
  size?: FieldSize;
  link?: boolean;
  text?: boolean;
  circle?: boolean;
  icon?: any;
  variant?: string;
  bg?: boolean;
}

export interface CardProps {
  bodyStyle?: Record<string, any>;
  shadow?: string;
  header?: string;
}

export interface CascaderProps {
  modelValue?: any;
  placeholder?: string;
  disabled?: boolean;
  clearable?: boolean;
  filterable?: boolean;
  options?: CascaderPropsOption[];
  size?: FieldSize;
  /** 弹出内容的自定义类名 */
  popperClass?: string;
  props: {
    expandTrigger?: 'click' | 'hover';
    multiple?: boolean;
    checkStrictly?: boolean;
    emitPath?: boolean;
    lazy?: boolean;
  };
}

export interface CheckboxProps {
  modelValue?: string | number | boolean;
  value?: string | number | boolean;
  label?: any;
  trueValue?: string | number;
  falseValue?: string | number;
  disabled?: boolean;
  size?: FieldSize;
}

export interface CheckboxGroupProps {
  modelValue?: any[];
  label?: string;
  disabled?: boolean;
  size?: FieldSize;
}

export interface ColProps {
  span?: number;
}

export interface CollapseProps {
  modelValue?: string | string[];
  accordion?: boolean;
}

export interface CollapseItemProps {
  name?: string | number;
  title?: string;
  disabled?: boolean;
}

export interface ColorPickerProps {
  modelValue?: string;
  disabled?: boolean;
  showAlpha?: boolean;
  size?: FieldSize;
}

export interface DatePickerProps {
  type?: string;
  modelValue?: any;
  disabled?: boolean;
  placeholder?: string;
  rangeSeparator?: string;
  startPlaceholder?: string;
  endPlaceholder?: string;
  format?: string;
  dateFormat?: string;
  timeFormat?: string;
  /** 可选，绑定值的格式。 不指定则绑定值为 Date 对象 */
  valueFormat?: string;
  /** 在范围选择器里取消两个日期面板之间的联动 */
  unlinkPanels?: boolean;
  defaultTime?: any;
  size?: FieldSize;
}

export interface DialogProps {
  modelValue?: boolean;
  appendToBody?: boolean;
  beforeClose?: any;
  title?: string;
  width?: string | number;
  fullscreen?: boolean;
  closeOnClickModal?: boolean;
  closeOnPressEscape?: boolean;
  destroyOnClose?: boolean;
  showClose?: boolean;
}

export interface DividerProps {
  direction?: string;
  borderStyle?: string;
  contentPosition?: string;
}

export interface DrawerProps {
  modelValue?: boolean;
  appendToBody?: boolean;
  beforeClose?: any;
  title?: string;
  size?: string | number;
  fullscreen?: boolean;
  closeOnClickModal?: boolean;
  closeOnPressEscape?: boolean;
  direction?: 'rtl' | 'ltr' | 'ttb' | 'bt';
}

export interface DropdownProps {
  type?: string;
  size?: string;
  maxHeight?: string | number;
  splitButton?: boolean;
  disable?: boolean;
  placement?: string;
  trigger?: string;
  hideOnClick?: boolean;
  showTimeout?: number;
  role?: string;
  tabindex?: number;
  popperClass?: string;
  popperOptions?: any;
}

export interface DropdownItemProps {
  command?: any;
  disabled?: boolean;
  divided?: boolean;
  icon?: any;
}

export interface FormProps {
  model?: any;
  labelWidth?: string | number;
  disabled?: boolean;
  inline?: boolean;
  labelPosition?: string;
}

export interface FormItemProps {
  prop?: string;
  labelWidth?: string | number;
  rules?: any;
  extra?: string;
  labelPosition?: 'top' | 'left' | 'right';
}

export interface InputProps {
  modelValue?: string | number;
  clearable?: boolean;
  disabled?: boolean;
  placeholder?: string;
  rows?: number;
  type?: string;
  size?: FieldSize;
  autosize?: boolean | { minRows: number; maxRows: number };
}

export interface InputNumberProps {
  modelValue?: string | number | boolean;
  clearable?: boolean;
  controlsPosition?: string;
  disabled?: boolean;
  placeholder?: string;
  step?: number;
  min?: number;
  max?: number;
  size?: FieldSize;
}

export interface OptionProps {
  value?: any;
  label?: string;
  disabled?: boolean;
}

export interface OptionGroupProps {
  label?: string;
  disabled?: boolean;
}

export interface PaginationProps {
  layout?: string;
  hideOnSinglePage?: boolean;
  curPage?: number;
  pageSizes?: number[];
  pageSize?: number;
  total?: number;
  size?: 'large' | 'default' | 'small';
}

export interface PopconfirmProps {
  title?: string;
  width?: string | number;
  /** 浮层是否插入到 body，默认 true。设为 false 时浮层内联渲染，便于嵌套在 hover 浮层中避免父级因 mouseleave 收起。 */
  teleported?: boolean;
  placement?:
    | 'top'
    | 'left'
    | 'right'
    | 'bottom'
    | 'top-left'
    | 'top-right'
    | 'bottom-left'
    | 'bottom-right'
    | 'left-top'
    | 'left-bottom'
    | 'right-top'
    | 'right-bottom';
}

export interface PopoverProps {
  placement?: Placement;
  width?: string | number;
  trigger?: 'hover' | 'click';
  disabled?: boolean;
  visible?: boolean;
  popperClass?: string;
  tabindex?: number;
  destroyOnClose?: boolean;
  /** 点击 popover 及其衍生浮层以外的区域时收起，默认开启。 */
  closeOnClickOutside?: boolean;
  /**
   * 追加的「点击不关闭」选择器，会与内置的弹窗 / 确认框 / 下拉等浮层选择器合并。
   * 用于 popover 内部触发、挂载到 body 之外的浮层不应顺带关闭 popover 的场景。
   */
  clickOutsideIgnore?: string;
}

export interface RadioProps {
  modelValue?: string | number | boolean;
  value?: string | number | boolean;
  label?: string | number | boolean;
}

export interface RadioButtonProps {
  value?: string | number | boolean;
  label?: string | number | boolean;
  disabled?: boolean;
  name?: string;
}

export interface RadioGroupProps {
  modelValue?: string | number | boolean;
  disabled?: boolean;
  size?: FieldSize;
}

export interface SelectProps {
  modelValue?: any;
  clearable?: boolean;
  filterable?: boolean;
  popperClass?: string;
  disabled?: boolean;
  placeholder?: string;
  remote?: boolean;
  multiple?: boolean;
  allowCreate?: boolean;
  valueKey?: string;
  remoteMethod?: any;
  loading?: boolean;
  size?: FieldSize;
  onSearch?: any;
}

export interface StepProps {
  title?: string;
  active?: number;
  props?: any;
  status?: any;
}

export interface StepsProps {
  active?: number;
  space?: number | string;
}

export interface SwitchProps {
  modelValue?: string | number | boolean;
  label?: any;
  activeValue?: string | number | boolean;
  inactiveValue?: string | number | boolean;
  disabled?: boolean;
  size?: FieldSize;
}

export interface TableProps {
  columns?: TableColumnOptions[];
  data?: any[];
  border?: boolean;
  maxHeight?: number | string;
  defaultExpandAll?: boolean;
  showHeader?: boolean;
  rowKey?: string;
  treeProps?: Record<string, any>;
  emptyText?: string;
  tooltipEffect?: string;
  tooltipOptions?: any;
  showOverflowTooltip?: boolean;
  spanMethod?: (data: any) => any;
}

export interface TableColumnOptions<T = any> {
  props: {
    class?: string;
    label?: string;
    fixed?: 'left' | 'right' | boolean;
    width?: number | string;
    type?: 'default' | 'selection' | 'index' | 'expand';
    prop?: string;
    align?: string;
    headerAlign?: string;
    sortable?: boolean | string;
    sortOrders?: Array<'ascending' | 'descending'>;
    selectable?: (row: T, index: number) => boolean;
  };
  cell?: (scope: { row: T; $index: number }) => any;
  title?: (scope?: any) => any;
}

export interface TabPaneProps {
  name?: string;
  label?: string;
  lazy?: boolean;
}

export interface TabsProps {
  type?: string;
  editable?: boolean;
  tabPosition?: 'left' | 'right' | 'top' | 'bottom';
  modelValue?: string | number;
}

export interface TagProps {
  type?: string;
  disableTransition?: boolean;
}

export interface TimePickerProps {
  modelValue?: any;
  disabled?: boolean;
  placeholder?: string;
  size?: FieldSize;
}

export interface TooltipProps {
  placement?: string;
  disabled?: boolean;
  content?: string;
  effect?: string;
  transition?: string;
  offset?: number;
}

export interface UploadProps {
  action?: string;
  autoUpload?: boolean;
  disabled?: boolean;
}

export interface CascaderPropsOption {
  /** 指定选项的值为选项对象的某个属性值 */
  value: any;
  /** 指定选项标签为选项对象的某个属性值 */
  label: string;
  /** 指定选项的子选项为选项对象的某个属性值 */
  children?: CascaderPropsOption[];
}

export interface IconProps {
  size?: string;
}

interface ExtraApi {
  success: (msg: string) => void;
  warning: (msg: string) => void;
  info: (msg: string) => void;
  error: (msg: string) => void;
  closeAll: () => void;
}

export type TMagicMessage = ExtraApi &
  ((options: {
    type?: 'info' | 'success' | 'warning' | 'error';
    message?: string;
    dangerouslyUseHTMLString?: boolean;
    duration?: number;
  }) => void);

export type ElMessageBoxShortcutMethod = ((
  message: string,
  title: string,
  options?: any,
  appContext?: any | null,
) => Promise<any>) &
  ((message: string, options?: any, appContext?: any | null) => Promise<any>);

export interface TMagicMessageBox {
  alert: ElMessageBoxShortcutMethod;

  confirm: ElMessageBoxShortcutMethod;

  prompt: ElMessageBoxShortcutMethod;

  close(): void;
}

export type LoadingBinding = boolean;

const INSTANCE_KEY = Symbol('TdesignLoading');

export interface ElementLoading extends HTMLElement {
  [INSTANCE_KEY]?: {
    instance: any;
  };
}

export interface Components {
  badge: {
    component: DefineComponent<BadgeProps, {}, any> | string;
    props: (props: BadgeProps) => BadgeProps;
  };

  autocomplete: {
    component: DefineComponent<AutocompleteProps, {}, any> | string;
    props: (props: AutocompleteProps) => AutocompleteProps;
  };

  button: {
    component: DefineComponent<ButtonProps, {}, any> | string;
    props: (props: ButtonProps) => ButtonProps;
  };

  card: {
    component: DefineComponent<CardProps, {}, any> | string;
    props: (props: CardProps) => CardProps;
  };

  cascader: {
    component: DefineComponent<CascaderProps, {}, any> | string;
    props: (props: CascaderProps) => CascaderProps;
  };

  checkbox: {
    component: DefineComponent<CheckboxProps, {}, any> | string;
    props: (props: CheckboxProps) => CheckboxProps;
  };

  checkboxGroup: {
    component: DefineComponent<CheckboxGroupProps, {}, any> | string;
    props: (props: CheckboxGroupProps) => CheckboxGroupProps;
  };

  col: {
    component: DefineComponent<ColProps, {}, any> | string;
    props: (props: ColProps) => ColProps;
  };

  collapse: {
    component: DefineComponent<CollapseProps, {}, any> | string;
    props: (props: CollapseProps) => CollapseProps;
  };

  collapseItem: {
    component: DefineComponent<CollapseItemProps, {}, any> | string;
    props: (props: CollapseItemProps) => CollapseItemProps;
  };

  colorPicker: {
    component: DefineComponent<ColorPickerProps, {}, any> | string;
    props: (props: ColorPickerProps) => ColorPickerProps;
  };

  datePicker: {
    component: DefineComponent<DatePickerProps, {}, any> | string;
    props: (props: DatePickerProps) => DatePickerProps;
  };

  dialog: {
    component: DefineComponent<DialogProps, {}, any> | string;
    props: (props: DialogProps) => DialogProps;
  };

  divider: {
    component: DefineComponent<DividerProps, {}, any> | string;
    props: (props: DividerProps) => DividerProps;
  };

  drawer: {
    component:
      | DefineComponent<
          DrawerProps,
          {
            handleClose: () => void;
          },
          any
        >
      | string;
    props: (props: DrawerProps) => DrawerProps;
  };

  dropdown: {
    component: DefineComponent<DropdownProps, {}, any> | string;
    props: (props: DropdownProps) => DropdownProps;
  };

  dropdownItem: {
    component: DefineComponent<DropdownItemProps, {}, any> | string;
    props: (props: DropdownItemProps) => DropdownItemProps;
  };

  dropdownMenu: {
    component: DefineComponent<{}, {}, any> | string;
    props: () => {};
  };

  form: {
    component: DefineComponent<FormProps, {}, any> | string;
    props: (props: FormProps) => FormProps;
  };

  formItem: {
    component: DefineComponent<FormItemProps, {}, any> | string;
    props: (props: FormItemProps) => FormItemProps;
  };

  icon: {
    component: DefineComponent<IconProps, {}, any> | string;
    props: (props: IconProps) => IconProps;
  };

  input: {
    component:
      | DefineComponent<
          InputProps,
          {
            instance: any;
            getInput: () => HTMLInputElement | undefined;
            getTextarea: () => HTMLTextAreaElement | undefined;
          },
          any
        >
      | string;
    props: (props: InputProps) => InputProps;
  };

  inputNumber: {
    component: DefineComponent<InputNumberProps, {}, any> | string;
    props: (props: InputNumberProps) => InputNumberProps;
  };

  option: {
    component: DefineComponent<OptionProps, {}, any> | string;
    props: (props: OptionProps) => OptionProps;
  };

  optionGroup: {
    component: DefineComponent<OptionGroupProps, {}, any> | string;
    props: (props: OptionGroupProps) => OptionGroupProps;
  };

  pagination: {
    component: DefineComponent<PaginationProps, {}, any> | string;
    props: (props: PaginationProps) => PaginationProps;
  };

  radio: {
    component: DefineComponent<RadioProps, {}, any> | string;
    props: (props: RadioProps) => RadioProps;
  };

  radioButton: {
    component: DefineComponent<RadioButtonProps, {}, any> | string;
    props: (props: RadioButtonProps) => RadioButtonProps;
  };

  radioGroup: {
    component: DefineComponent<RadioGroupProps, {}, any> | string;
    props: (props: RadioGroupProps) => RadioGroupProps;
  };

  row: {
    component: DefineComponent<{}, {}, any> | string;
    props: () => {};
  };

  scrollbar: {
    component: DefineComponent<{}, {}, any> | string;
    props: () => {};
  };

  select: {
    component:
      | DefineComponent<
          SelectProps,
          {
            scrollbarWrap: HTMLDivElement | undefined;
            setQuery: (v: string) => void;
            setPreviousQuery: (v: string) => void;
            setSelectedLabel: (v: string) => void;
            setSelected: () => void;
          },
          any
        >
      | string;
    props: (props: SelectProps) => SelectProps;
  };

  step: {
    component: DefineComponent<StepProps, {}, any> | string;
    props: (props: StepProps) => StepProps;
  };

  steps: {
    component: DefineComponent<StepsProps, {}, any> | string;
    props: (props: StepsProps) => StepsProps;
  };

  switch: {
    component: DefineComponent<SwitchProps, {}, any> | string;
    props: (props: SwitchProps) => SwitchProps;
  };

  table: {
    component:
      | DefineComponent<
          TableProps,
          {
            getEl: () => HTMLElement | undefined;
            getTableRef: () => any;
            clearSelection: (...args: any[]) => void;
            toggleRowSelection: (...args: any[]) => void;
            toggleRowExpansion: (...args: any[]) => void;
          },
          any
        >
      | string;
    props: (props: TableProps) => TableProps;
  };

  tabPane: {
    component: DefineComponent<TabPaneProps, {}, any> | string;
    props: (props: TabPaneProps) => TabPaneProps;
  };

  tabs: {
    component: DefineComponent<TabsProps, {}, any> | string;
    props: (props: TabsProps) => TabsProps;
  };

  tag: {
    component: DefineComponent<TagProps, {}, any> | string;
    props: (props: TagProps) => TagProps;
  };

  timePicker: {
    component: DefineComponent<TimePickerProps, {}, any> | string;
    props: (props: TimePickerProps) => TimePickerProps;
  };

  tooltip: {
    component: DefineComponent<TooltipProps, {}, any> | string;
    props: (props: TooltipProps) => TooltipProps;
  };

  upload: {
    component:
      | DefineComponent<
          UploadProps,
          {
            clearFiles: (...args: any[]) => any;
          },
          any
        >
      | string;
    props: (props: UploadProps) => UploadProps;
  };

  popconfirm: {
    component: DefineComponent<PopconfirmProps, {}, any> | string;
    props: (props: PopconfirmProps) => PopconfirmProps;
  };
}

export interface DesignPluginOptions {
  adapterType?: string;
  message?: TMagicMessage;
  messageBox?: TMagicMessageBox;
  components?: Components;
  loading?: Directive<ElementLoading, LoadingBinding>;
  useZIndex?: (zIndexOverrides?: Ref<number>) => {
    initialZIndex: ComputedRef<number>;
    currentZIndex: ComputedRef<number>;
    nextZIndex: () => number;
  };
  [key: string]: any;
}
