import { Arrayable, EpPropMergeType } from 'element-plus/es/utils'
import { FormItemRule, SingleOrRange } from 'element-plus'
import { StrAnyObj, StrAnyObjArr } from '@/typings'

export type FormConfigType =
  | InputType
  | InputNumberType
  | SelectType
  | RadioType
  | CheckboxType
  | DatePickerType
  | FormSlotType
  | UploadType

export interface InputType extends FormCommonType {
  type: 'input'
  // 占位符
  placeholder?: string
  // 是否可以清空选项
  clearable?: boolean | (() => boolean)
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // 是否只读
  readonly?: boolean | (() => boolean)
  // 类型
  itemType?: 'text' | 'textarea' | 'password'
  // 最大输入长度
  maxlength?: number
  // 最小输入长度
  minlength?: number
  // 是否显示统计字数, 只在 type 为 'text' 或 'textarea' 的时候生效
  showWordLimit?: boolean
  // 是否显示切换密码图标
  showPassword?: boolean
  // 输入框行数，仅 type 为 'textarea' 时有效
  rows?: number
  // textarea 高度是否自适应，仅 type 为 'textarea' 时生效。 可以接受一个对象，比如: { minRows: 2, maxRows: 6 }
  autosize?: boolean | { minRows?: number; maxRows?: number }
  // 控制是否能被用户缩放
  resize?: 'none' | 'both' | 'horizontal' | 'vertical'
  // change事件
  change?: (value: any) => void
}

export interface InputNumberType extends FormCommonType {
  // 类型
  type: 'inputNumber'
  // 占位符
  placeholder?: string
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // 是否只读
  readonly?: boolean | (() => boolean)
  // 设置计数器允许的最小值
  min?: number
  // 设置计数器允许的最大值
  max?: number
  // 数值精度
  precision?: number
  // 计数器步长
  step?: number
  // 是否只能输入计数器步长的倍数
  stepStrictly?: boolean
  // 是否使用控制按钮
  controls?: boolean
  // 当输入框被清空时显示的值
  valueOnClear?: number | null | 'min' | 'max'
  // change事件
  change?: (value: any) => void
}

export interface SelectType extends FormCommonType, FormOptionType {
  // 类型
  type: 'select'
  // 占位符
  placeholder?: string
  // 是否可以清空选项
  clearable?: boolean | (() => boolean)
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // 是否可以筛选
  filterable?: boolean
  // 是否可以多选
  multiple?: boolean
  // change事件
  change?: (value: any) => void
}

export interface RadioType extends FormCommonType, FormOptionType {
  // 类型
  type: 'radio'
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // change事件
  change?: (value: any) => void
}

export interface CheckboxType extends FormCommonType, FormOptionType {
  // 类型
  type: 'checkbox'
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // change事件
  change?: (value: any) => void
}

export interface DatePickerType extends FormCommonType {
  // 类型
  type: 'datePicker'
  // 占位符
  placeholder?: string
  // 是否可以清空选项
  clearable?: boolean | (() => boolean)
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // 是否只读
  readonly?: boolean | (() => boolean)
  // 显示类型
  datePickerType?:
    | 'year'
    | 'years'
    | 'month'
    | 'date'
    | 'dates'
    | 'datetime'
    | 'week'
    | 'datetimerange'
    | 'daterange'
    | 'monthrange'
  // 显示在输入框中的格式
  format?: string
  // 绑定值的格式。 不指定则绑定值为 Date 对象
  valueFormat?: string
  // 选择器打开时默认显示的时间
  defaultValue?: Date | [Date, Date]
  // 选择日期后的默认时间值。 如未指定则默认时间值为 00:00:00
  defaultTime?: EpPropMergeType<
    | (new (...args: any[]) => Date | [Date, Date])
    | (() => SingleOrRange<Date>)
    | ((new (...args: any[]) => Date | [Date, Date]) | (() => SingleOrRange<Date>))[],
    unknown,
    unknown
  >
  // 一个用来判断该日期是否被禁用的函数
  disabledDate?: (data: Date) => boolean
  // 设置快捷选项
  shortcuts?: Array<{ text: string; value: Date | Function }>
  // 范围选择时开始日期的占位内容
  startPlaceholder?: string
  // 范围选择时结束日期的占位内容
  endPlaceholder?: string
  // 选择范围时的分隔符
  rangeSeparator?: string
  // change事件
  change?: (value: any) => void
}

export interface UploadType extends FormCommonType {
  // 类型
  type: 'upload'
  // 是否禁用
  disabled?: boolean | (() => boolean)
  // 提示
  tip: string
  // 最大上传数量
  limit: number
  // 组件宽度
  width: string
}

export interface FormSlotType extends FormCommonType {
  // 类型
  type: 'slot'
}

interface FormCommonType {
  // 绑定属性
  prop: string
  // 标签文本
  label?: string
  // 栅格占据的列数
  span?: number
  // 是否存在
  if?: boolean | (() => boolean)
  // 是否显示
  show?: boolean | (() => boolean)
  // 验证
  rule?: Arrayable<FormItemRule>
  // 样式
  style?: StrAnyObj
  // 访问权限列表
  permissions?: string | string[]
}

export interface FormOptionType {
  // 自动加载列表
  autoLoadOption?: boolean
  // 获取列表值
  option?:
    | StrAnyObjArr
    | Promise<StrAnyObjArr>
    | (() => StrAnyObjArr)
    | (() => Promise<StrAnyObjArr>)
  // 绑定key名称
  keyName?: string
  // 绑定label名称
  labelName?: string
  // 绑定disabled名称
  disabledName?: string
  // 字典key
  dict?: string
}
