import { TableColumnType, TableProps, TooltipProps } from 'ant-design-vue';
import { ButtonProps } from 'ant-design-vue/lib/button';
import type { Rule } from 'ant-design-vue/lib/form';
import { FormProps } from 'ant-design-vue/lib/form/Form';
import { ColProps } from 'ant-design-vue/lib/grid/Col';
import type { BorderConfigValue, ConfigType, Column as EVirtColumn } from 'e-virt-table';
import EVirtTable from 'e-virt-table';

export type { BorderConfigValue, BorderStyle } from 'e-virt-table';
/** 与 e-virt-table `scrollbarMode` 对齐：`outer` 外部预留，`inner` 内部悬停显示 */
export type ScrollbarMode = 'outer' | 'inner';

export interface CellFuncArg<D extends Recordable = Recordable> {
  row: D;
  column?: ColumnProps<D>;
  rowIndex: number;
  cellValue: any;
}
export type FormatterFunc = (c: CellFuncArg, ...args: any[]) => any;
export type PFormatter = Record<string, FormatterFunc>;
export interface ItemFuncArg<F extends Recordable = Recordable> {
  data: F;
  field?: string;
}

export interface ItemRender {
  name: string;
  defaultValue?: any;
  props?: Recordable;
  attrs?: Recordable;
  options?: IOption[];
  children?: Recordable[];
  events?: { [key: string]: (...args: any[]) => any };
}

export interface CellRender {
  name: string;
  props?: Recordable;
  attrs?: Recordable;
  children?: Recordable[];
}

export interface Responsive {
  xxs?: number;
  xs?: number;
  sm?: number;
  md?: number;
  lg?: number;
  xl?: number;
  xxl?: number;
}

export interface TooltipConfig extends TooltipProps {
  title: TooltipProps['title'] | (() => any);
}

export interface PFormItemProps<F extends Recordable = Recordable> {
  field?: string;
  title?: string;
  span?: number;
  colon?: boolean;
  labelCol?: ColProps;
  wrapperCol?: ColProps;
  forceRequired?: boolean; // 在页面需要必填标示，但field不需要必填校验时使用
  align?: 'left' | 'right' | 'center';
  col?: ColProps;
  rule?: Rule[];
  itemRender?: ItemRender;
  tooltipConfig?: TooltipConfig;
  slots?: {
    title?: () => any;
    default?: (
      { data, field }: ItemFuncArg<F>,
      passTrigger?: (cusFields?: string | string[]) => void,
      passDelayTrigger?: (cusFields?: string | string[], time?: number) => void,
    ) => any;
    defaultValue?: any;
  };
}

export interface PFormProps<F extends Recordable = Recordable> extends FormProps {
  name?: string;
  items: PFormItemProps<F>[];
  customReset?: () => void;
}

export interface PSearchFormProps<F extends Recordable = Recordable> extends Omit<
  PFormProps<F>,
  'items'
> {
  data: F;
  items: PFormItemProps<F>[];
  loading?: boolean;
  /** 是否通过 PForm 的原有 reset 流程重置 data，默认 true */
  autoReset?: boolean;
  /** 是否自动追加查询、重置操作项，默认 true */
  showActions?: boolean;
}

export type PGridFormConfig<F extends Recordable = Recordable> = Omit<PFormProps<F>, 'items'> & {
  /** 查询表单项；传入后自动追加查询、重置按钮，并优先于 items */
  searchItems?: PFormItemProps<F>[];
  /** 兼容旧用法，按原配置渲染，不自动追加按钮 */
  items?: PFormItemProps<F>[];
};

export interface PDescriptionItemProps<D extends Recordable = Recordable> {
  field?: string;
  label?: string;
  span?: number;
  labelStyle?: Recordable;
  contentStyle?: Recordable;
  /** 只读展示渲染器，派发到 renderStore.renderDefault */
  readonlyRender?: ItemRender;
  slots?: {
    label?: () => any;
    default?: ({ data, field }: { data: D; field?: string }) => any;
  };
}

export interface PDescriptionProps<D extends Recordable = Recordable> {
  /** 数据源 */
  data: D;
  items: PDescriptionItemProps<D>[];
  /** 透传 a-descriptions */
  title?: string;
  extra?: string;
  bordered?: boolean;
  size?: 'default' | 'small' | 'middle';
  column?: number | Partial<Record<'xxs' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl', number>>;
  layout?: 'horizontal' | 'vertical';
  colon?: boolean;
  labelStyle?: Recordable;
  contentStyle?: Recordable;
  /** 缺省占位，row[field] 为空时展示 */
  emptyText?: string;
}

export interface PBlockProps<F extends Recordable = Recordable> {
  name?: string;
  getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
  source: Partial<F>;
}

export interface PromisePickerProps<
  D extends Recordable = Recordable,
  F extends Recordable = Recordable,
> {
  gridSetting: PGridProps<D, F>;
  title?: string;
  width?: string | number;
  multipleAllowEmpty?: boolean;
  bodyStyle?: Recordable;
  beforePick?: (rowOrRows: D | Array<D>) => Promise<void>;
}

export type GroupMenuItemHandler<F extends Recordable = Recordable> = ({
  index,
  data,
  code,
}: {
  index: number;
  code: string;
  data: Partial<F & { __index: number }>;
}) => void;

export interface GroupMenuItem<F extends Recordable = Recordable> {
  content: string;
  icon?: string;
  code: string;
  visibleMethod?: ({ data, index }: { data: Partial<F>; index: number }) => boolean;
}

export interface PFormGroupProps<F extends Recordable = Recordable> {
  name?: string;
  getFormSetting: (data: Partial<F>) => PFormProps<Partial<F>>;
  title?: string;
  tabLabel?: string;
  /**
   * 获取完整标签页标签
   * @param data 数据
   * @param idx 实际索引
   * @returns 标签页标签
   */
  getTabLabel?: (data: Partial<F>, idx: number) => string;
  editAble?: boolean;
  showAdd?: boolean;
  /* 是否启用折叠 */
  collapsible?: boolean;
  /** 是否默认折叠 */
  defaultCollapsed?: boolean;
  lazyErrorMark?: boolean;
  forceRender?: boolean;
  /* 是否保持连续编号 */
  keepSerial?: boolean;
  loading?: boolean;
  itemMenus?: Array<GroupMenuItem<F>>;
  createItem?: ({ list }: { list?: Partial<F>[] }) => Promise<Partial<F>>;
  max?: number;
  menuHandler?: GroupMenuItemHandler<F>;
}

export interface ColumnProps<D extends Recordable = Recordable> extends Omit<
  TableColumnType,
  'slots'
> {
  field?: string;
  children?: ColumnProps<D>[];
  formatter?:
    | string
    | [string, ...Array<any>]
    | ((arg: PartialByKeys<CellFuncArg<D>, 'cellValue'>) => any);
  slots?: {
    default?: ({ row, column, rowIndex }: PartialByKeys<CellFuncArg<D>, 'cellValue'>) => any;
    title?: ({ column }: { column: ColumnProps<D> }) => any;
  };
  cellRender?: CellRender;
}

export interface PButtonProps extends Omit<ButtonProps, 'type'> {
  content?: string | (() => any);
  icon?: string;
  /** 与 `a-button` 一致，便于模板类型检查 */
  type?: ButtonProps['type'];
}

export interface ToolbarButtonProps extends PButtonProps {
  code?: string;
  dropdowns?: ToolbarButtonProps[];
}
export interface ToolbarToolProps extends PButtonProps {
  code: string;
}
export interface ToolbarConfig {
  buttons?: Array<ToolbarButtonProps>;
  tools?: Array<ToolbarToolProps>;
  disabled?: boolean;
}

export interface ResponsePathConfig<D extends Recordable = Recordable> {
  /*非分页取值路径*/
  list?: string | ((res: Recordable) => D[]);
  /*分页取值路径*/
  result?: string | ((res: Recordable) => D[]);
  total?: string | ((res: Recordable) => D[]);
  /*提示信息取值路径*/
  message?:
    | string
    | ((res: Recordable) => string | { status: string; content: string; icon?: string });
}

export type HandlerMultiDel = (ids: Array<string | number>) => any;

export interface AjaxConfig<F extends Recordable = Recordable> {
  query: (Q: { page?: IPage; form: Partial<F> }) => Promise<Recordable>;
  multiDelete?: HandlerMultiDel;
}

export interface ProxyConfig<D extends Recordable = Recordable, F extends Recordable = Recordable> {
  // 结果集 取值路径
  response?: ResponsePathConfig<D>;
  ajax: AjaxConfig<F>;
}

export interface PageConfig {
  pageSizes?: number[];
  pageSize?: number;
  showSizeChanger?: boolean;
  showQuickJumper?: boolean;
}

export interface SelectConfig<D extends Recordable = Recordable> {
  multiple?: boolean;
  showCount?: boolean;
  getCheckboxProps?: (record: D) => { disabled?: boolean };
}

export type PGridProps<D extends Recordable = Recordable, F extends Recordable = Recordable> = {
  selectConfig?: SelectConfig<D>;
  rowKey?: string;
  striped?: boolean;
  manualFetch?: boolean;
  align?: 'left' | 'right' | 'center';
  formConfig?: PGridFormConfig<F>;
  columns?: ColumnProps<D>[];
  toolbarConfig?: ToolbarConfig;
  pageConfig?: PageConfig;
  proxyConfig?: ProxyConfig<D, F>;
  tableConfig?: TableProps<D>;
  scrollMode?: 'outer' | 'inner';
  /**
   * 为 true 时根容器按视口从左上角铺满（与 v-rest 同源），用于外层未声明高度、靠内部撑开的布局。
   * 偏移见 `autoBoxSizeOffset`。
   */
  autoBoxSize?: boolean;
  /**
   * `autoBoxSize` 时距视口右侧/底部的预留像素；数字或 `"12px"` 同时作用于两侧；对象可分别指定 `right` / `bottom`。
   * 未传时使用 `setUIKitConfig({ grid: { autoBoxSizeOffset } })` 的全局值。
   */
  autoBoxSizeOffset?: number | string | { right?: number; bottom?: number };
  // 重置后不自动提交
  lazyReset?: boolean;
  /**
   * 表格纵向滚动区额外预留像素：在 `tableWrapper` 高度内扣减表头、底栏后，再从 body 可滚动高度中减去本值，避免末行与滚动条贴边或被裁切。可通过 `setUIKitConfig({ grid: { fitHeight } })` 或组件 `fitHeight` 按项目微调；库内全局默认见 `config`。
   */
  fitHeight?: number;
  /**
   * 适应展示区到页面顶部的canvas渲染高度 通常比table的小
   */
  fitCanvasHeight?: number;
  /**
   * 虚拟列表 Y区计算高度
   */
  renderY?: number;
  /**
   * 适应「外层高度由内容撑开」的布局（典型如弹窗 `PromisePicker`）。
   *
   * 开启后：
   * - 根容器/表体宿主不再 `flex:1` 强行撑满（避免父无固定高度时塌陷到 0）；
   * - `a-table` 的纵向 `scroll.y` 作为「最多滚动到多少」的上限，由 `renderY` 显式指定；
   *   若不传 `renderY`，使用基于视口的默认值。内容少时不会出现行区域下方的大片空白。
   */
  fitContent?: boolean;
};

export interface RenderOptions {
  /**
   * 渲染器名称
   */
  name?: string;
  /**
   * 目标组件渲染的参数
   */
  props?: { [key: string]: any };
  /**
   * 目标组件渲染的属性
   */
  attrs?: { [key: string]: any };
  /**
   * 目标组件渲染的事件
   */
  events?: { [key: string]: (...args: any[]) => any };
  /**
   * 多目标渲染
   */
  children?: any[];
  /**
   * 选项
   */
  options?: IOption[];
  /**
   * 默认值
   */
  defaultValue?: any;
  /**
   * 校验触发器
   * @param cusFields field或者field数组
   */
  handleTrigger?: (cusFields?: string | string[]) => void;
  /**
   * 延迟校验触发器
   * @param cusFields field或者field数组
   * @param time 延迟时间
   */
  handleDelayTrigger?: (cusFields?: string | string[], time?: number) => void;
}

export interface RenderFormParams<F extends Recordable = Recordable> {
  data: F;
  field?: string;
}

export interface RenderReadonlyParams<D extends Recordable = Recordable> {
  data: D;
  field?: string;
  title?: string;
}

export interface RenderTableParams<D extends Recordable = Recordable> {
  data?: D[];
  row: D;
  rowIndex?: number;
  field?: string;
  title?: string;
}
export interface CanvasColumnProps<T extends Recordable = Recordable> extends Omit<
  EVirtColumn,
  'children' | 'formatter' | 'key'
> {
  key?: string;
  field?: string;
  children?: CanvasColumnProps<T>[];
  formatter?:
    | string
    | [string, ...Array<any>]
    | ((arg: PartialByKeys<CellFuncArg<T>, 'cellValue'>) => any);
  slots?: {
    default?: ({
      row,
      column,
      rowIndex,
    }: {
      row: T;
      column: CanvasColumnProps<T>;
      rowIndex: number;
    }) => any;
    edit?: ({
      row,
      column,
      rowIndex,
    }: {
      row: T;
      column: CanvasColumnProps<T>;
      rowIndex: number;
    }) => any;
    title?: ({ column }: { column: CanvasColumnProps<T> }) => any;
  };
  cellRender?: CellRender;
  editRender?: CellRender;
}
export interface CanvasTableProps<
  T extends Recordable = Recordable,
  B extends Recordable = Recordable,
> {
  columns: CanvasColumnProps<T>[];
  data: T[];
  config?: ConfigType;
  footerData?: B[];
  loading?: boolean;
}

export interface PCanvasGridProps<
  D extends Recordable = Recordable,
  F extends Recordable = Recordable,
> {
  staticConfig?: {
    selectable?: boolean;
    showCount?: boolean;
    tree?: boolean;
  };
  manualFetch?: boolean;
  formConfig?: PGridFormConfig<F>;
  columns: CanvasColumnProps<D>[];
  toolbarConfig?: ToolbarConfig;
  pageConfig?: PageConfig;
  proxyConfig?: ProxyConfig<D, F>;
  config?: ConfigType;
  /**
   * 表格边框样式，映射 e-virt-table `BORDER`。
   * - `true` / `'default'`：完整单元格边框
   * - `'outer'`：仅外边框
   * - `'inner'` / `false`：仅内部横线
   * - `'none'`：无边框
   * 显式传入时优先于 `config.BORDER`。
   */
  border?: BorderConfigValue;
  /**
   * 滚动条模式，映射 e-virt-table `scrollbarMode`。
   * - `'outer'`：外部预留滚动条轨道（默认）
   * - `'inner'`：覆盖在内容上，悬停表格内部后显示
   * 显式传入时优先于 `config.scrollbarMode`。
   */
  scrollbarMode?: ScrollbarMode;
  /**
   * 内部滚动条（`scrollbarMode: 'inner'`）悬停后显示延迟（ms），映射 `SCROLLBAR_SHOW_DELAY`。
   * 显式传入时优先于 `config.SCROLLBAR_SHOW_DELAY`。
   */
  scrollbarShowDelay?: number;
  // 重置后不自动提交
  lazyReset?: boolean;
  /**
   * 适应展示区到页面顶部的高度，通常和容器最上的y值有关（正比）
   */
  fitHeight?: number;
  /**
   * 开启后组件根节点按视口从其左上角铺满宽高，与 PGrid 的 autoBoxSize 行为一致。
   * 外层未声明固定高度、需组件自身占满可视区域时使用。
   */
  autoBoxSize?: boolean;
  /**
   * `autoBoxSize` 时距视口右侧/底部的预留像素；数字或 `"12px"` 同时作用于两侧；对象可分别指定 `right` / `bottom`。
   * 未传时使用 `setUIKitConfig({ grid: { autoBoxSizeOffset } })` 的全局值。
   */
  autoBoxSizeOffset?: number | string | { right?: number; bottom?: number };
}
export interface PGridInstance<
  D extends Recordable = Recordable,
  F extends Recordable = Recordable,
> {
  commitProxy: {
    query: () => Promise<D[]>;
    reload: () => Promise<D[]>;
    reloadPage: () => Promise<D[]>;
    passQuery: (query: Partial<F>, lazy?: boolean) => Promise<void | D[]>;
    forcePassQuery: (query: Partial<F>, lazy?: boolean) => Promise<void | D[]>;
  };
  selectedRowKeys: string[] | number[];
  selectedRecords: D[];
  $table: Recordable;
  $form: Recordable;
  getFormData: () => Partial<F>;
  setLoadings: (value: boolean) => void;
  setBtnLoading: (code: string, status: boolean) => void;
  resizeTable: () => void;
}

export interface PFormInstance {
  reset: () => void;
  $form: Recordable;
}

export interface PromisePickerInstance<D extends Recordable = Recordable> {
  pick: () => Promise<{ row: D; field?: string }>;
  pickMultiple: () => Promise<D[]>;
  grid: PGridInstance<D>;
  hide: () => void;
}

export interface PFormBlockInstance {
  $form: Recordable;
}

export interface PFormGroupInstance {
  activeKey: number;
  setActiveKey: (activeKey: number) => void;
  /** 按数组下标删除一项，并清理校验缓存 / 激活态 */
  removeItem: (index: number) => void;
  validateAll: () => Promise<void>;
  validate: (index: number, ignoreTabError?: boolean) => Promise<void>;
  validateFields: (index: number, fields: string[], ignoreTabError?: boolean) => Promise<void>;
  collapse: () => void;
  expand: () => void;
}
export interface PCanvasTableInstance<T extends Recordable = Recordable> {
  $table: InstanceType<typeof EVirtTable>;
  selectedRecords: T[];
  clearSelection: () => void;
  setLoading: (value: boolean) => void;
}
