<template>
  <a-form
    v-bind="formItemLayout"
    :layout="props.layout"
    autocomp
    lete="off"
  >
    <a-form-item
      v-for="item in formProps"
      :key="item.key"
      :label="item.label"
      v-bind="validateInfos[item.key]"
    >
      <input-tsx v-if="item.type === 'input'" :style="{width: props.itemWidth ? props.itemWidth : null}"  v-model="modelRef[item.key]" />
      <select-tsx  v-else-if="item.type === 'select'" :style="{width: props.itemWidth}" :request="item.request" v-model="modelRef[item.key]" :on-change="(e) => onChange(e, item.key)"  />
      <textarea-tsx  v-else-if="item.type === 'textarea'"  :style="{width: props.itemWidth ? props.itemWidth : null}" v-model="modelRef[item.key]"  />
    </a-form-item>
    <!-- <a-form-item>
      <slot name="reset" > <a-button @click="resetForm">重置</a-button></slot>
    </a-form-item> -->
    <a-form-item v-if="props.search" >
      <slot name="search" > <a-button type="primary" @click="search">搜索</a-button></slot>
    </a-form-item>
  </a-form>

</template>

<script lang='ts' setup >
import { computed, onMounted, reactive, toRaw } from 'vue'
import { Form } from 'ant-design-vue'
import { InputTsx, SelectTsx, TextareaTsx } from './components/indext'

/**
 * 将submit的提交抛出去
 */
export interface FormItemProps {
  rules?: {required: boolean, message: string} | boolean,
  type: COMMON.COMPONENTS.ComType,
  key: string,
  value?: any,
  label: string,
  request?: () => Promise<{
    name: string,
    value: any,
    key: string
  }[]>
}

/**
* 直接将table的columns传入时进行数据转化处理
 */
export interface ColumnsProps {
  title: string,
  dataIndex: string,
  key?: string,
  formProps?: FormItemProps
}

export interface FormProProps {
  labelCol: any
  reset?: boolean // 是否开启一键reset表单
  search?: boolean // 是否开启搜索功能
  validate: boolean // 是否开启验证功能
  layout?: 'horizontal' | 'vertical' | 'inline', // 布局方式 默认横向布局
  itemWidth: string // 每个表单控件的长度
  formProps?: FormItemProps[] // 表单props
  columnsProps?: ColumnsProps[] // 与table表格一起传入的时候, 便于从table表格中筛选
  [key: string]: any
}

enum ComponentTypeEnum {
  'input' = 'input',
  'select' = 'select'
}

const componentTypes: COMMON.COMPONENTS.ComType[] = ['input', 'select', 'datepick']

const formItemLayout = computed(() => {
  return propsState.layout === 'horizontal'
    ? {
        labelCol: props.labelCol ? props.labelCol : { span: 4 },
        wrapperCol: { span: 14 }
      }
    : {}
})

const getLablePrefix = (key: COMMON.COMPONENTS.ComType) => {
  switch (key) {
    case 'input':
      return '请填写'
    case 'select':
      return '请选择'
    default:
      return '请填写'
  }
}

const useForm = Form.useForm

const emit = defineEmits(['submit', 'reset', 'search'])

const props = defineProps<FormProProps>()

const propsState = reactive({
  layout: 'horizontal'
})

const initFormPro = () => {
  if (props.formProps) {
    props.formProps.forEach((item: FormItemProps) => {
      const key = item.key
      rulesRef[key] = typeof item.rules === 'object' ? item.rules : [{ required: item.rules, message: getLablePrefix(item.type) + item.label }]
      modelRef[key] = item.value || ''
      formProps.push({ ...item })
    })
  } else {
    props.columnsProps.forEach((item: ColumnsProps) => {
      if (item.formProps) {
        const key = item.formProps!.key ? item.formProps!.key : item.dataIndex
        const rules = typeof item.formProps!.rules === 'object'
          ? item.formProps!.rules
          : [{ required: item.formProps!.rules, message: getLablePrefix(item.formProps.type) + item.title }]

        rulesRef[key!] = rules
        modelRef[item.formProps.key] = item.formProps.value || ''
        formProps.push({ ...item.formProps })
      }
    })
  }

  propsState.layout = props.layout ? props.layout : 'horizontal'
}

const modelRef = reactive<Record<string, any>>({})

const rulesRef = reactive<Record<string, any>>({})

const formProps = reactive<FormItemProps[]>([])

const onChange = (record: any, key: string) => {
  modelRef[key] = record
}

const { resetFields, validate, validateInfos } = useForm(modelRef, rulesRef)

const search = async () => {
  const r = await onSubmit()
  emit('search', r)
}

const onSubmit = () => {
  return new Promise((resolve, reject) => {
    validate()
      .then(() => {
        resolve(modelRef)
      })
      .catch(err => {
        reject(err)
      })
  })
}

defineExpose({
  onSubmit
})

onMounted(() => {
  initFormPro()
})

</script>

<style lang="less" scope >
:deep(.ant-form-inline .ant-form-item ){
  margin-bottom: 10px !important;
}

::v-deep .ant-form-inline .ant-form-item  {
  margin-bottom: 10px !important;
}

:deep(.ant-form-inline),
:deep(.ant-form-item) {
  margin-bottom: 10px !important;
}
</style>
