<template>
  <ele-drawer
    :size="430"
    title="表单项配置"
    :append-to-body="true"
    style="max-width: 100%"
    :model-value="modelValue"
    :body-style="{ paddingLeft: '10px' }"
    @update:modelValue="updateModelValue"
  >
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="92px"
      @submit.prevent=""
    >
      <el-form-item label="标题" prop="label">
        <el-input
          clearable
          :maxlength="20"
          v-model="form.label"
          placeholder="请输入标题"
        />
      </el-form-item>
      <el-form-item label="字段名" prop="prop">
        <el-input
          clearable
          :maxlength="20"
          v-model="form.prop"
          placeholder="请输入字段名"
        />
      </el-form-item>
      <el-form-item label="是否必填" prop="required">
        <el-radio-group v-model="form.required">
          <el-radio :value="true" label="是" />
          <el-radio :value="false" label="否" />
        </el-radio-group>
      </el-form-item>
      <el-form-item prop="itemProps">
        <el-input
          :rows="2"
          type="textarea"
          v-model="form.itemProps"
          placeholder="请输入 ElFormItem 属性"
        />
        <template #label>
          <ele-tooltip
            placement="top-start"
            :popperOptions="{
              modifiers: [{ name: 'offset', options: { offset: [-12, 10] } }]
            }"
          >
            <el-icon
              :size="15"
              style="align-self: center; margin-right: 4px; cursor: help"
            >
              <QuestionCircleOutlined style="opacity: 0.6" />
            </el-icon>
            <template #content>
              <div>配置 ElFormItem 组件的其它属性(JSON格式)，如：</div>
              <div>{"rules": [{"required": true, "type": "string", </div>
              <div>"message": "请输入标题", "trigger": "blur"}]}</div>
            </template>
          </ele-tooltip>
          <div>其它属性</div>
        </template>
      </el-form-item>
      <el-form-item label="组件类型" prop="type">
        <el-select
          v-model="form.type"
          placeholder="请选择组件类型"
          class="ele-fluid"
          @change="onTypeChange"
        >
          <el-option
            v-for="item in typeOptions"
            :key="item.value"
            :value="item.value"
            :label="item.label"
          />
        </el-select>
      </el-form-item>
      <el-form-item prop="props">
        <el-input
          :rows="5"
          type="textarea"
          v-model="form.props"
          placeholder="请输入组件属性"
        />
        <template #label>
          <ele-tooltip
            placement="top-start"
            :popperOptions="{
              modifiers: [{ name: 'offset', options: { offset: [-12, 10] } }]
            }"
          >
            <el-icon
              :size="15"
              style="align-self: center; margin-right: 4px; cursor: help"
            >
              <QuestionCircleOutlined style="opacity: 0.6" />
            </el-icon>
            <template #content>
              <div>配置组件的属性(JSON格式)，如：</div>
              <div>{"clearable": false, "maxlength": 20}</div>
            </template>
          </ele-tooltip>
          <div>组件属性</div>
        </template>
      </el-form-item>
      <el-form-item label="所占列数" prop="colSpan">
        <el-select
          v-model="form.colSpan"
          placeholder="请选择所占列数"
          class="ele-fluid"
        >
          <el-option
            v-for="item in gridOptions"
            :key="item.value"
            :label="item.label"
            :value="item.value"
            :disabled="item.value > grid"
          />
        </el-select>
      </el-form-item>
      <el-form-item prop="options">
        <el-input
          :rows="5"
          type="textarea"
          v-model="form.options"
          placeholder="请输入选项数据"
        />
        <template #label>
          <ele-tooltip
            placement="top-start"
            :popperOptions="{
              modifiers: [{ name: 'offset', options: { offset: [-12, 10] } }]
            }"
          >
            <el-icon
              :size="15"
              style="align-self: center; margin-right: 4px; cursor: help"
            >
              <QuestionCircleOutlined style="opacity: 0.6" />
            </el-icon>
            <template #content>
              <div>下拉或多选、单选等组件的选项数据(JSON格式)，如：</div>
              <div>
                [{"label": "男", "value": 1}, {"label": "女", "value": 2}]
              </div>
            </template>
          </ele-tooltip>
          <div>选项数据</div>
        </template>
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button type="primary" class="ele-fluid" @click="save">保存</el-button>
    </template>
  </ele-drawer>
</template>

<script lang="ts" setup>
  import { ref, reactive, watch } from 'vue';
  import type { FormInstance, FormRules } from 'element-plus/es';
  import { QuestionCircleOutlined } from '@/components/icons';
  import { useFormData } from '@/utils/use-form-data';
  import type { ProFormItemProps } from '@/components/ProForm/types';
  import {
    gridOptions,
    itemTypes,
    getOptionsAndProps,
    getColProps,
    getColSpan
  } from './util';

  const emit = defineEmits<{
    (e: 'done', data: ProFormItemProps): void;
    (e: 'update:modelValue', modelValue: boolean): void;
  }>();

  const props = defineProps<{
    /** 弹窗是否打开 */
    modelValue: boolean;
    /** 修改回显的数据 */
    data?: ProFormItemProps | null;
    /** 表单显示列数 */
    grid: number;
  }>();

  /** 配置项表单 */
  const formRef = ref<FormInstance | null>(null);

  /** 配置项表单数据 */
  const [form, resetFields, assignFields] = useFormData({
    key: void 0,
    label: '',
    prop: '',
    required: false,
    itemProps: '',
    type: void 0,
    props: '',
    //colProps: '',
    options: '',
    colSpan: 1
  });

  /** 验证JSON格式 */
  const validateJSON = (value?: string) => {
    if (value) {
      const msg = '请输入正确的JSON格式';
      try {
        const obj = JSON.parse(value);
        if (obj == null || typeof obj !== 'object') {
          return msg;
        }
      } catch (_e) {
        return msg;
      }
    }
  };

  /** 配置项表单验证规则 */
  const rules = reactive<FormRules>({
    label: [
      {
        required: true,
        type: 'string',
        message: '请输入标题',
        trigger: 'blur'
      }
    ],
    prop: [
      {
        required: true,
        type: 'string',
        message: '请输入字段名',
        trigger: 'blur'
      }
    ],
    itemProps: [
      {
        validator: (_rule: any, value: string, callback: any) => {
          callback(validateJSON(value));
        },
        trigger: 'blur'
      }
    ],
    props: [
      {
        validator: (_rule: any, value: string, callback: any) => {
          callback(validateJSON(value));
        },
        trigger: 'blur'
      }
    ],
    colProps: [
      {
        validator: (_rule: any, value: string, callback: any) => {
          callback(validateJSON(value));
        },
        trigger: 'blur'
      }
    ]
  });

  /** 组件类型下拉数据 */
  const typeOptions = ref(
    itemTypes.map((d) => {
      return { ...d, label: `${d.label}(${d.value})` };
    })
  );

  /** 组件类型选择改变 */
  const onTypeChange = (type: string) => {
    const { options, props } = getOptionsAndProps(type);
    form.props = props;
    form.options = options;
  };

  /** 保存表单项配置 */
  const save = () => {
    formRef.value?.validate?.((valid) => {
      if (valid) {
        //updateModelValue(false);
        emit('done', {
          key: form.key,
          label: form.label,
          prop: form.prop,
          type: form.type,
          required: form.required,
          itemProps: form.itemProps ? JSON.parse(form.itemProps) : void 0,
          props: form.props ? JSON.parse(form.props) : void 0,
          //colProps: form.colProps ? JSON.parse(form.colProps) : void 0,
          colProps: getColProps(props.grid, form.colSpan),
          options: form.options ? JSON.parse(form.options) : void 0
        });
      }
    });
  };

  /** 更新modelValue */
  const updateModelValue = (value: boolean) => {
    emit('update:modelValue', value);
  };

  watch(
    () => props.modelValue,
    (modelValue) => {
      if (modelValue) {
        const item = props.data;
        if (item) {
          assignFields({
            ...item,
            itemProps: item.itemProps
              ? JSON.stringify(item.itemProps, void 0, 2)
              : '',
            props: item.props ? JSON.stringify(item.props, void 0, 2) : '',
            //colProps: item.colProps ? JSON.stringify(item.colProps, void 0, 2) : '',
            options: item.options
              ? JSON.stringify(item.options, void 0, 2)
              : '',
            colSpan: getColSpan(props.grid, item.colProps?.span)
          });
        }
      } else {
        resetFields();
        formRef.value?.clearValidate?.();
      }
    }
  );
</script>
