declare module 'global-type' {
  import {
    ElTable,
    ElTableColumn,
    ElInput,
    ElInputNumber,
    ElAutocomplete,
    ElSwitch,
    ElRadioGroup,
    ElRadio,
    ElCheckboxGroup,
    ElCheckbox,
    ElSelect,
    ElOptionGroup,
    ElOption,
    ElDatePicker,
    ElForm,
    ElFormItem,
    ElRow,
    ElCol,
    ElCheckboxButton,
    ElRadioButton,
  } from 'element-plus'
  import type { VNode, Component, DefineComponent, VNodeProps } from 'vue'
  import BaseTable from '@/components/element/BaseTable.vue'
  import BaseForm from '@/components/element/BaseForm.vue'
  import BaseSelect from '@/components/element/BaseSelect.vue'
  import BaseCheckBox from '@/components/element/BaseCheckBox.vue'
  import BaseRadio from '@/components/element/BaseRadio.vue'
  import type {
    TableProps,
    FormProps,
    FormItemProps,
    InputProps,
    InputNumberProps,
    RadioProps,
    CheckboxProps,
    AutocompleteProps,
    SwitchProps,
    FormRules,
    FormItemRule,
    RowProps,
    ColProps,
    SelectOptionProxy,
  } from 'element-plus'
  import type { TableColumnCtx } from 'element-plus/es/components/table/src/table-column/defaults'
  import MarkHeaderVue from '@/components/shared/MarkHeader.vue'

  export type MarkHeaderInstance = InstanceType<typeof MarkHeaderVue>

  export type ExtractComponentProps<T extends DefineComponent> = Mutable<
    Omit<InstanceType<T>['$props'], keyof VNodeProps>
  >

  export type CI<T> = {
    column: TableColumnCtx<T>
    $index: number
  }

  export type Filters = {
    text: string
    value: string
  }[]

  export type FilterMethods<T> = (value: any, row: T, column: TableColumnCtx<T>) => void

  export interface EpTableProps<T = any>
    extends AssignKeys<ExtractComponentProps<typeof ElTable>, Partial<TableProps<T>>> {
    columns?: EpTableColumn<T>[]
  }

  export type EpTableColumn<T = any> = AssignKeys<
    ExtractComponentProps<typeof ElTableColumn>,
    Partial<{
      type: 'selection' | 'index' | 'expand'
      renderHeader: (data: CI<T>) => VNode
      sortMethod: (a: T, b: T) => number
      sortBy: string | ((row: T, index: number) => string) | string[]
      formatter: (row: T, column: TableColumnCtx<T>, cellValue: any, index: number) => VNode | string
      align: 'left' | 'center' | 'right'
      headerAlign: 'left' | 'center' | 'right'
      selectable: (row: T, index: number) => boolean
      filters: Filters
      filterMethod: FilterMethods<T>
    }>
  > & { slotName?: string }

  export interface FormSupportComponentMap {
    input: typeof ElInput
    inputNumber: typeof ElInputNumber
    autocomplete: typeof ElAutocomplete
    switch: typeof ElSwitch
    radio: typeof BaseRadio
    checkbox: typeof BaseCheckBox
    select: typeof BaseSelect
    date: typeof ElDatePicker
    dateTime: typeof ElDatePicker
  }

  export type ElFormItemProps = Omit<
    AssignKeys<ExtractComponentProps<typeof ElFormItem>, Partial<FormItemProps>>,
    'lineMessage'
  >

  export type FormItemCustomProp<T extends keyof FormSupportComponentMap, U extends Record<string, unknown>> = {
    hidden?: boolean
    slotType?: T
    slotName?: string
    slot?: Partial<AssignKeys<ExtractComponentProps<FormSupportComponentMap[T]>, Mutable<U>>>
  }

  export type WithCustomProp<T extends keyof FormSupportComponentMap, U extends Record<string, unknown>> = AssignKeys<
    ElFormItemProps,
    FormItemCustomProp<T, U>
  >

  export type FormItemInput = WithCustomProp<'input', InputProps>

  export type FormItemInputNumber = WithCustomProp<'inputNumber', InputNumberProps>

  export type FormItemAutocomplete = WithCustomProp<'autocomplete', AutocompleteProps>

  export type FormItemSwitch = WithCustomProp<'switch', SwitchProps>

  export type BaseRadioProp = AssignKeys<
    ExtractComponentProps<typeof ElRadio>,
    RadioProps & { slotLabel?: string | VNode }
  >

  export type BaseRadioButtonProp = AssignKeys<
    ExtractComponentProps<typeof ElRadioButton>,
    { slotLabel?: string | VNode }
  >

  export type FormItemRadioCustomOptions = BaseRadioProp[] | BaseRadioButtonProp[]

  export type FormItemRadioCustomProp = AssignKeys<
    ExtractComponentProps<typeof ElRadioGroup>,
    {
      options?: FormItemRadioCustomOptions
    }
  >

  export type FormItemRadio = WithCustomProp<'radio', FormItemRadioCustomProp>

  export type BaseCheckBoxProp = AssignKeys<
    ExtractComponentProps<typeof ElCheckbox>,
    CheckboxProps & { slotLabel?: string | VNode }
  >

  export type BaseCheckBoxButtonProp = AssignKeys<
    ExtractComponentProps<typeof ElCheckboxButton>,
    { slotLabel?: string | VNode }
  >

  export type FormItemCheckBoxCustomOptions = BaseCheckBoxProp[] | BaseCheckBoxButtonProp[]

  export type FormItemCheckBoxCustomProp = AssignKeys<
    ExtractComponentProps<typeof ElCheckboxGroup>,
    {
      options?: FormItemCheckBoxCustomOptions
    }
  >

  export type FormItemCheckBox = WithCustomProp<'checkbox', FormItemCheckBoxCustomProp>

  export type BaseOptionGroupProp = AssignKeys<ExtractComponentProps<typeof ElOptionGroup>, object>

  export type BaseOptionProp = AssignKeys<ExtractComponentProps<typeof ElOption>, object>

  export type FormItemSelectCustomOptionGroup = Record<string | number, BaseOptionGroupProp>
  export type FormItemSelectCustomOptions = AssignKeys<BaseOptionProp, { groupKey?: string | number }>[]

  export type FormItemSelectCustomProp = AssignKeys<
    ExtractComponentProps<typeof ElSelect>,
    {
      optionGroup?: FormItemSelectCustomOptionGroup
      options?: FormItemSelectCustomOptions
    }
  >

  export type FormItemSelect = WithCustomProp<'select', FormItemSelectCustomProp>

  export type FormItemDatePicker = WithCustomProp<'date', object>

  export type FormItemDateTimePicker = WithCustomProp<'dateTime', object>

  export type FormItemDescriptionProp = {
    itemDescription?: {
      requiredAsterisk?: boolean
      description: string
    }
  }

  export type WithDescriptionProp<T> = AssignKeys<T, FormItemDescriptionProp>

  export type BaseElRowProp = AssignKeys<ExtractComponentProps<typeof ElRow>, Partial<RowProps>>

  export type FormItemRowProp = { rowKey?: string | number }

  export type WithRowProp<T> = AssignKeys<T, FormItemRowProp>

  export type BaseElColProp = AssignKeys<ExtractComponentProps<typeof ElCol>, Partial<ColProps>>

  export type FormItemColProp = {
    colProp?: Partial<BaseElColProp>
    colIndex?: number
  }

  export type WithColProp<T> = AssignKeys<T, FormItemColProp>

  export type PolymerizationFormItem<T> = WithRowProp<WithColProp<WithDescriptionProp<T>>>

  export type SupportFormItemType =
    | FormItemInput
    | FormItemInputNumber
    | FormItemAutocomplete
    | FormItemSwitch
    | FormItemRadio
    | FormItemCheckBox
    | FormItemSelect
    | FormItemDatePicker
    | FormItemDateTimePicker

  export type EpFormItem =
    | PolymerizationFormItem<FormItemInput>
    | PolymerizationFormItem<FormItemInputNumber>
    | PolymerizationFormItem<FormItemAutocomplete>
    | PolymerizationFormItem<FormItemSwitch>
    | PolymerizationFormItem<FormItemRadio>
    | PolymerizationFormItem<FormItemCheckBox>
    | PolymerizationFormItem<FormItemSelect>
    | PolymerizationFormItem<FormItemDatePicker>
    | PolymerizationFormItem<FormItemDateTimePicker>

  export type EpFormRows = Record<
    string | number,
    AssignKeys<BaseElRowProp, { rowKey?: string | number; hidden?: boolean }>
  >

  export type FormGroup = {
    hidden?: boolean
    groupKey?: string | number
    groupTitle?: string | VNode
    rowKeys?: (string | number)[]
  }

  export type BaseFormProp = AssignKeys<ExtractComponentProps<typeof ElForm>, Partial<FormProps>>

  export interface EpFormProps<T extends Record<string, unknown> = Record<string, unknown>>
    extends Omit<BaseFormProp, 'inline' | 'line-message' | 'lineMessage'> {
    // 使用的栅格布局,inline失效
    model: T
    items?: EpFormItem[]
    rows?: EpFormRows
    groups?: FormGroup[]
  }

  export type EpFormRules<T extends Record<string, unknown> = Record<string, unknown>> = EpFormProps<T>['rules']

  export type InstanceTable = InstanceType<typeof BaseTable>
  export type InstanceElTable = InstanceType<typeof ElTable>
  export type InstanceForm = InstanceType<typeof BaseForm>
  export type InstanceSelect = InstanceType<typeof BaseSelect>
  export type InstanceCheckBox = InstanceType<typeof BaseCheckBox>
  export type InstanceRadio = InstanceType<typeof BaseRadio>
}
