import type { ButtonProps, ButtonType, TagProps } from 'element-plus'
import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'

import type { Component, ComponentPublicInstance } from 'vue'

import type Table from '#/components/table/index.vue'

declare global {
  interface anyObj {
    [key: string]: any
  }

  interface Page {
    current: number | string
    size: number | string
    total: number | string
  }

  /* 表格行 */
  interface TableRow extends anyObj {
    children?: TableRow[]
  }

  /* 表头支持的按钮 */
  type HeaderOptButton =
    | 'add'
    | 'columnDisplay'
    | 'comSearch'
    | 'delete'
    | 'edit'
    | 'quickSearch'
    | 'recycle bin'
    | 'refresh'
    | 'unfold'

  /* 链接打开方式 */
  type aTarget = '_blank' | '_self'

  /* 通用搜索事件返回的Data */
  interface comSearchData {
    field: string
    operator: string
    render?: string
    val: string
  }

  interface ElTreeData {
    children?: ElTreeData[]
    label: string
  }

  /*
   * ElTableColumn可用属性
   * 未找到方法直接导出tableColumn的props类型定义
   * https://element-plus.org/zh-CN/component/table.html#table-column-attributes
   */
  interface ElTableColumn {
    align?: 'center' | 'left' | 'right'
    'class-name'?: string
    'column-key'?: string
    'filter-method'?: any
    'filter-multiple'?: boolean
    'filter-placement'?: string
    'filtered-value'?: any[]
    filters?: { key: string; value: string }[]
    fixed?: boolean | string
    formatter?: any
    'header-align'?: 'center' | 'left' | 'right'
    index?: any | number
    label?: string
    'label-class-name'?: string
    'min-width'?: number | string
    prop?: string
    'render-header'?: any
    'reserve-selection'?: boolean
    resizable?: boolean
    selectable?: any
    'show-overflow-tooltip'?: boolean
    'sort-by'?: any
    'sort-method'?: any
    'sort-orders'?: null[] | string[]
    sortable?: boolean | string
    type?: 'expand' | 'index' | 'selection' | 'sort'
    width?: number | string
  }

  interface Scope {
    $index: number
    cellIndex: number
    column: ElTableColumn
    row: anyObj
    store: any
  }

  /* 表格列 */
  interface TableColumn extends ElTableColumn {
    // 操作按钮组
    // buttons?: OptButton[]
    buttons?: any[]
    // 渲染为:url 时的点击事件
    click?: (
      row: TableRow,
      field: TableColumn,
      value: any,
      column: TableColumnCtx<TableRow>,
      index: number,
    ) => any
    // 公共搜索自定义组件/函数渲染
    comSearchCustomRender?: Component | string
    // 公共搜索渲染方式:上方的 render=tag|switch 时公共搜索也会渲染为下拉，数字会渲染为范围筛选，时间渲染为时间选择器等
    comSearchRender?: 'customRender' | 'date' | 'remoteSelect' | 'select'
    // 自定义数据:比如渲染为Tag时,可以指定不同值时的Tag的Type属性 { open: 'success', close: 'info' }
    custom?: any
    // 自定义组件/函数渲染
    customRender?: Component | string
    // 谨慎使用：自定义渲染模板，方法可返回html内容，请确保返回内容是xss安全的
    customTemplate?: (
      row: TableRow,
      field: TableColumn,
      value: any,
      column: TableColumnCtx<TableRow>,
      index: number,
    ) => string
    // 默认值
    default?: any
    // 渲染为Tag时:el-tag 组件的主题
    effect?: TagProps['effect']
    // 是否在下拉菜单的复选框显示 默认为true显示
    enableColumnDisplayControl?: boolean
    // 通用搜索框的placeholder
    operatorPlaceholder?: string
    // 远程属性
    remote?: {
      field?: string
      multiple?: boolean
      params?: anyObj
      pk?: string
      remoteUrl: string
    }
    // 渲染为:icon|switch|image|images|tag|url|datetime|buttons|customTemplate|customRender
    render?: (h: Component, scope: Scope) => any
    // 使用了 render 属性时,渲染前对字段值的预处理方法，请返回新值
    renderFormatter?: (
      row: TableRow,
      field: TableColumn,
      value: any,
      column: TableColumnCtx<TableRow>,
      index: number,
    ) => any
    // 值替换数据,如{open: '开'}
    replaceValue?: any
    // 是否显示
    show?: boolean
    // 渲染为Tag时:el-tag 组件的size
    size?: TagProps['size']
    // 渲染为链接时,链接的打开方式
    target?: aTarget
    // 渲染为 datetime 时的格式化方式,字母可以自由组合:y=年,m=月,d=日,h=时,M=分,s=秒，默认：yyyy-mm-dd hh:MM:ss
    timeFormat?: string
  }

  /* 表格右侧操作按钮 */
  interface OptButton {
    // 自定义el-button属性
    attr?: Partial<ButtonProps>
    class?: string
    // 自定义点击事件
    click?: (row: TableRow, field: TableColumn) => void
    // 按钮是否禁用，请返回布尔值
    disabled?: (row: TableRow, field: TableColumn) => boolean
    disabledTip?: boolean
    // 按钮是否显示，请返回布尔值
    display?: (row: TableRow, field: TableColumn) => boolean
    icon: string
    name: string
    popconfirm?: any
    // 渲染方式:tipButton=带tip的按钮,confirmButton=带确认框的按钮,moveButton=移动按钮
    render: string
    text?: string
    title?: string
    type: ButtonType
  }

  /* XbTable */
  interface XbTable {
    // 接受url的query参数并自动触发通用搜索
    acceptQuery?: boolean
    // 表单事件
    action?: { [key: string]: any }
    // 是否有边框
    border?: boolean
    // 表格列定义
    column: TableColumn[]
    // 表格数据，通过getIndex加载
    data?: TableRow[]
    // 不需要'双击编辑'的字段，type=selection的列为 undefined
    dblClickNotEditColumn?: (string | undefined)[]
    // 字段搜索,快速搜索,分页等数据
    // filter?: {
    //     page?: number
    //     limit?: number
    //     order?: string
    //     quick_search?: string
    //     search?: comSearchData[]
    //     [key: string]: any
    // }
    // 默认排序字段和排序方式
    defaultOrder?: { order: string; prop: string }
    // 拖动排序限位字段:例如拖动行pid=1,那么拖动目的行pid也需要为1
    dragSortLimitField?: string
    // 是否展开所有子项，树状表格专用属性
    expandAll?: boolean
    expandRowKeys?: string[]
    // 表格扩展数据，随意定义，以便一些自定义数据可以随baTable实例传递
    extend?: anyObj
    headerCellStyle?: any
    // 表格头样式
    headerRowStyle?: any
    // 布局
    layout?: {
      // 分页是否简化
      shrink?: boolean
    }
    // 表格加载状态
    loading?: boolean
    // 移动行数据
    moveRow?: anyObj
    // 移动后触发事件
    onRowMove?: any
    // 分页数据
    page: Page
    // 分页选项
    pageSizes?: number[]
    // 表格对应数据表的主键字段
    pk?: string
    // 表格 ref，通常在 页面onMounted 时赋值
    ref?: typeof Table
    // 路由 remark，后台菜单规则备注信息
    remark?: null | string
    // 移动目的行数据
    replaceRow?: anyObj
    // 移动目的行后的数据
    replaceRowAfter?: anyObj
    // 移动目的行前的数据
    replaceRowBefore?: anyObj
    // 当前选中行
    selection?: TableRow[]
    // 显示公共搜索
    showComSearch?: boolean
    // 是否开启斑马纹
    stripe?: boolean
  }

  interface TableRenderPublicInstance extends ComponentPublicInstance {
    $attrs: {
      renderField: TableColumn
      renderRow: TableRow
      renderValue: any
    }
  }
}
