<template>
  <div class="fc-style" style="padding: 20px;">
    <el-form ref="generateForm" label-suffix=":" :model="state.model" :rules="state.rules"
      :size="state.widgetForm.config.size" :label-position="state.widgetForm.config.labelPosition"
      :label-width="`${state.widgetForm.config.labelWidth}px`"
      :hide-required-asterisk="state.widgetForm.config.hideRequiredAsterisk">
      <template v-for="(element, index) of state.widgetForm.list">
        <template v-if="element.type === 'grid'">
          <el-row type="flex" v-if="element.key" :key="element.key" :gutter="element.options.gutter ?? 0"
            :justify="element.options.justify" :align="element.options.align">
            <el-col v-for="(col, colIndex) of element.columns" :key="colIndex" :span="col.span ?? 0">
              <ElGenerateFormItem v-for="colItem of col.list" :model="state.model" :key="colItem.key" :element="colItem"
                :config="data.config" :disabled="disabled" />
            </el-col>
          </el-row>
        </template>
        <ElGenerateFormItem v-else :model="state.model" :key="element.key" :element="state.widgetForm.list[index]"
          :config="data.config" :disabled="disabled" />
      </template>
    </el-form>
  </div>
</template>

<script lang="ts" setup>
import { onMounted, reactive, toRefs, watch, ref } from 'vue'
import { ElMessage } from 'element-plus'
import ElGenerateFormItem from './ElGenerateFormItem.vue'
import { element } from '../../config'


const props = defineProps({
  data: {
    type: Object,
    default: element.widgetForm
  },
  value: {
    type: Object
  },
  disabled: {
    type: Boolean,
    default: false
  }
})

const generateForm = ref()

const state = reactive({
  model: {} as any,
  rules: {} as any,
  widgetForm:
    (props.data && JSON.parse(JSON.stringify(props.data))) ??
    element.widgetForm
})
const generateModel = (list: any[]) => {
  for (let index = 0; index < list.length; index++) {
    const model = list[index].model
    if (!model) {
      return
    }
    if (list[index].type === 'grid') {
      list[index].columns.forEach((col: any) => generateModel(col.list))
    } else {
      if (props.value && Object.keys(props.value).includes(model)) {
        state.model[model] = props.value[model]
      } else {
        state.model[model] = list[index].options.defaultValue
      }

      state.rules[model] = list[index].options.rules
    }
  }
}

const generateOptions = (list: any[]) => {
  list.forEach(item => {
    if (item.type === 'grid') {
      item.columns.forEach((col: any) => generateOptions(col.list))
    } else {
      if (item.options.remote && item.options.remoteFunc) {
        fetch(item.options.remoteFunc)
          .then(resp => resp.json())
          .then(json => {
            if (json instanceof Array) {
              item.options.remoteOptions = json.map(data => ({
                label: data[item.options.props.label],
                value: data[item.options.props.value],
                children: data[item.options.props.children]
              }))
            }
          })
      }
    }
  })
}

watch(
  () => props.data,
  val => {
    state.widgetForm =
      (val && JSON.parse(JSON.stringify(val))) ?? element.widgetForm
    state.model = {}
    state.rules = {}
    generateModel(state.widgetForm.list)
    generateOptions(state.widgetForm.list)
  },
  { deep: true, immediate: true }
)

onMounted(() => {
  generateModel(state.widgetForm?.list ?? [])
  generateOptions(state.widgetForm?.list ?? [])
})

const getData = () => {
  return new Promise((resolve, reject) => {
    generateForm.value.validate().then((validate: boolean) => {
      if (validate) {
        // console.log('成功', state.generateForm);
        resolve(state.model)
      } else {
        // console.log('失败');
        ElMessage.error('验证失败')
      }
    }).catch((error: Error) => {
      reject(error)
    })
  })
}

const reset = () => {
  generateForm.value.resetFields()
}

defineExpose({
  ...toRefs(state),
  getData,
  reset
})
</script>
