<template>
  <!-- drawer -->
  <template v-if="modalConfig.component === 'drawer'">
    <el-drawer v-model="modalVisible" :append-to-body="true" v-bind="modalConfig.drawer" @close="handleCloseModal">
      <!-- 表单 -->
      <el-form ref="formRef" label-width="auto" v-bind="modalConfig.form" :model="formData" :rules="formRules">
        <el-row :gutter="20">
          <template v-for="item in formItems" :key="item.prop">
            <template v-if="item.type === 'title'">
              <h3>{{ item.label }}</h3>
            </template>
            <el-col v-else v-show="!item.hidden" v-bind="item.col">
              <el-form-item :label="item.label" :prop="item.prop">
                <!-- Label -->
                <template v-if="item.tips" #label>
                  <span>
                    {{ item.label }}
                    <el-tooltip placement="bottom" effect="light" :content="item.tips" :raw-content="true">
                      <el-icon style="vertical-align: -0.15em" size="16">
                        <QuestionFilled />
                      </el-icon>
                    </el-tooltip>
                  </span>
                </template>
                <!-- Input 输入框 -->
                <template v-if="item.type === 'input' || item.type === undefined">
                  <el-input v-model="formData[item.prop]" v-bind="item.attrs" />
                </template>
                <!-- textarea 输入框 -->
                <template v-else-if="item.type === 'textarea'">
                  <el-input v-model="formData[item.prop]" v-bind="item.attrs" type="textarea" />
                </template>
                <!-- Select 选择器 -->
                <template v-else-if="item.type === 'select'">
                  <el-select v-model="formData[item.prop]" v-bind="item.attrs">
                    <template v-for="option in item.options" :key="option.value">
                      <el-option v-bind="option" />
                    </template>
                  </el-select>
                </template>
                <!-- radio-button 选择器 -->
                <template v-else-if="item.type === 'radio-button'">
                  <el-radio-group v-model="formData[item.prop]" v-bind="item.attrs">
                    <template v-for="option in item.options" :key="option.value">
                      <el-radio-button v-bind="option" />
                    </template>
                  </el-radio-group>
                </template>
                <!-- Radio 单选框 -->
                <template v-else-if="item.type === 'radio'">
                  <el-radio-group v-model="formData[item.prop]" v-bind="item.attrs">
                    <template v-for="option in item.options" :key="option.value">
                      <el-radio v-bind="option" />
                    </template>
                  </el-radio-group>
                </template>
                <!-- switch 开关 -->
                <template v-else-if="item.type === 'switch'">
                  <el-switch v-model="formData[item.prop]" inline-prompt v-bind="item.attrs" />
                </template>
                <!-- Checkbox 多选框 -->
                <template v-else-if="item.type === 'checkbox'">
                  <el-checkbox-group v-model="formData[item.prop]" v-bind="item.attrs">
                    <template v-for="option in item.options" :key="option.value">
                      <el-checkbox v-bind="option" />
                    </template>
                  </el-checkbox-group>
                </template>
                <!-- Input Number 数字输入框 -->
                <template v-else-if="item.type === 'input-number'">
                  <el-input-number v-model="formData[item.prop]" v-bind="item.attrs" />
                </template>
                <!-- TreeSelect 树形选择 -->
                <template v-else-if="item.type === 'tree-select'">
                  <el-tree-select v-model="formData[item.prop]" v-bind="item.attrs" />
                </template>
                <!-- DatePicker 日期选择器 -->
                <template v-else-if="item.type === 'date-picker'">
                  <el-date-picker v-model="formData[item.prop]" v-bind="item.attrs" />
                </template>
                <!-- 图片上传 -->
                <template v-else-if="item.type === 'UpImage'">
                  <SingleImageUpload v-model="formData[item.prop]" />
                </template>
                <!-- Text 文本 -->
                <template v-else-if="item.type === 'text'">
                  <el-text v-bind="item.attrs">
                    {{ formData[item.prop] }}
                  </el-text>
                </template>
                <!-- 自定义 -->
                <template v-else-if="item.type === 'custom'">
                  <slot :name="item.slotName ?? item.prop" :prop="item.prop" :formData="formData" :attrs="item.attrs" />
                </template>
              </el-form-item>
            </el-col>
          </template>
        </el-row>
      </el-form>
      <!-- 表单底部插槽 -->
      <slot name="formFooter" />
      <!-- 弹窗底部操作按钮 -->
      <template #footer>
        <div v-if="!formDisable">
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
          <el-button @click="handleClose">取 消</el-button>
        </div>
        <div v-else>
          <el-button @click="handleClose">关闭</el-button>
        </div>
      </template>
    </el-drawer>
  </template>
  <!-- dialog -->
  <template v-else>
    <el-dialog v-model="modalVisible" :align-center="true" :append-to-body="true" width="70vw"
      v-bind="modalConfig.dialog" style="padding-right: 0" @close="handleCloseModal">
      <!-- 滚动 -->
      <el-scrollbar max-height="60vh">
        <!-- 表单 -->
        <el-form ref="formRef" label-width="auto" v-bind="modalConfig.form"
          style="padding-right: var(--el-dialog-padding-primary)" :model="formData" :rules="formRules">
          <el-row :gutter="20">
            <template v-for="item in formItems" :key="item.prop">
              <template v-if="item.type === 'title'">
                <el-col :span="24">
                  <h3>{{ item.label }}</h3>
                </el-col>
              </template>
              <el-col v-else v-show="!item.hidden" v-bind="item.col">
                <el-form-item :label="item.label" :prop="item.prop">
                  <!-- Label -->
                  <template v-if="item.tips" #label>
                    <span>
                      {{ item.label }}
                      <el-tooltip placement="bottom" effect="light" :content="item.tips" :raw-content="true">
                        <el-icon style="vertical-align: -0.15em" size="16">
                          <QuestionFilled />
                        </el-icon>
                      </el-tooltip>
                    </span>
                  </template>
                  <!-- Input 输入框 -->
                  <template v-if="item.type === 'input' || item.type === undefined">
                    <el-input v-model="formData[item.prop]" v-bind="item.attrs" :disabled="item.disabled" />
                  </template>
                  <!-- textarea 输入框 -->
                  <template v-else-if="item.type === 'textarea'">
                    <el-input v-model="formData[item.prop]" v-bind="item.attrs" type="textarea" />
                  </template>

                  <!-- Select 选择器 -->
                  <template v-else-if="item.type === 'select'">
                    <el-select v-model="formData[item.prop]" v-bind="item.attrs">
                      <template v-for="option in item.options" :key="option.value">
                        <el-option v-bind="option" />
                      </template>
                    </el-select>
                  </template>
                  <!-- radio-button 选择器 -->
                  <template v-else-if="item.type === 'radio-button'">
                    <el-radio-group v-model="formData[item.prop]" v-bind="item.attrs">
                      <template v-for="option in item.options" :key="option.value">
                        <el-radio-button v-bind="option" />
                      </template>
                    </el-radio-group>
                  </template>
                  <!-- Radio 单选框 -->
                  <template v-else-if="item.type === 'radio'">
                    <el-radio-group v-model="formData[item.prop]" v-bind="item.attrs">
                      <template v-for="option in item.options" :key="option.value">
                        <el-radio v-bind="option" />
                      </template>
                    </el-radio-group>
                  </template>
                  <!-- switch 开关 -->
                  <template v-else-if="item.type === 'switch'">
                    <el-switch v-model="formData[item.prop]" inline-prompt v-bind="item.attrs" />
                  </template>
                  <!-- Checkbox 多选框 -->
                  <template v-else-if="item.type === 'checkbox'">
                    <el-checkbox-group v-model="formData[item.prop]" v-bind="item.attrs">
                      <template v-for="option in item.options" :key="option.value">
                        <el-checkbox v-bind="option" />
                      </template>
                    </el-checkbox-group>
                  </template>
                  <!-- Input Number 数字输入框 -->
                  <template v-else-if="item.type === 'input-number'">
                    <el-input-number v-model="formData[item.prop]" v-bind="item.attrs" />
                  </template>
                  <!-- TreeSelect 树形选择 -->
                  <template v-else-if="item.type === 'tree-select'">
                    <el-tree-select v-model="formData[item.prop]" v-bind="item.attrs" />
                  </template>
                  <!-- DatePicker 日期选择器 -->
                  <template v-else-if="item.type === 'date-picker'">
                    <el-date-picker v-model="formData[item.prop]" v-bind="item.attrs" />
                  </template>
                  <template v-else-if="item.type === 'time-picker'">
                    <el-time-picker value-format="HH:mm:ss" v-model="formData[item.prop]" is-range range-separator="到"
                      start-placeholder="开始时间" end-placeholder="结束时间" />
                  </template>

                  <!-- Text 文本 -->
                  <template v-else-if="item.type === 'text'">
                    <el-text v-bind="item.attrs">
                      {{ formData[item.prop] }}
                    </el-text>
                  </template>
                  <!-- 图片上传 -->
                  <template v-else-if="item.type === 'UpImage'">
                    <SingleImageUpload v-model="formData[item.prop]" />
                  </template>
                  <!-- 自定义 -->
                  <template v-else-if="item.type === 'custom'">
                    <slot :name="item.slotName ?? item.prop" :prop="item.prop" :formData="formData"
                      :attrs="item.attrs" />
                  </template>
                </el-form-item>
              </el-col>
            </template>
          </el-row>
        </el-form>
      </el-scrollbar>
      <!-- 表单底部插槽 -->
      <slot name="formFooter" />
      <!-- 弹窗底部操作按钮 -->
      <template #footer>
        <div style="padding-right: var(--el-dialog-padding-primary)">
          <el-button type="primary" @click="handleSubmit">确 定</el-button>
          <el-button @click="handleClose">取 消</el-button>
        </div>
      </template>
    </el-dialog>
  </template>
</template>

<script setup lang="ts">
import { useThrottleFn } from "@vueuse/core";
import type { FormInstance, FormRules } from "element-plus";
import { nextTick, reactive, ref, watch, watchEffect } from "vue";
import type { IModalConfig, IObject } from "./types";
// import SingleImageUpload from "@/components/Upload/SingleImageUpload.vue";
// 定义接收的属性
const props = defineProps<{
  modalConfig: IModalConfig;
}>();
// 自定义事件
const emit = defineEmits<{
  submitClick: [];
  formDataChange: [string, any];
}>();
const pk = props.modalConfig.pk ?? "id";
const modalVisible = ref(false);
const formRef = ref<FormInstance>();
const formItems = reactive(props.modalConfig.formItems);
const formData = reactive<IObject>({});
const formRules: FormRules = {};
const formDisable = ref(false);
const prepareFuncs = [];
for (const item of formItems) {
  item.initFn && item.initFn(item);
  formData[item.prop] = item.initialValue ?? "";
  formRules[item.prop] = item.rules ?? [];

  if (item.watch !== undefined) {
    prepareFuncs.push(() => {
      watch(
        () => formData[item.prop],
        (newValue, oldValue) => {
          emit("formDataChange", item.prop, newValue);
          item.watch && item.watch(newValue, oldValue, formData, formItems);
        }
      );
    });
  }

  if (item.computed !== undefined) {
    prepareFuncs.push(() => {
      watchEffect(() => {
        item.computed && (formData[item.prop] = item.computed(formData));
      });
    });
  }

  if (item.watchEffect !== undefined) {
    prepareFuncs.push(() => {
      watchEffect(() => {
        item.watchEffect && item.watchEffect(formData);
      });
    });
  }
}
prepareFuncs.forEach((func) => func());

// 获取表单数据
function getFormData(key?: string) {
  return key === undefined ? formData : formData[key] ?? undefined;
}

// 设置表单值
function setFormData(data: IObject) {
  for (const key in formData) {
    if (formData.hasOwnProperty(key) && key in data) {
      formData[key] = data[key];
    }
  }
  if (data?.hasOwnProperty(pk)) {
    formData[pk] = data[pk];
  }
}

// 设置表单项值
function setFormItemData(key: string, value: any) {
  formData[key] = value;
}

// 显示modal
function setModalVisible(data: IObject = {}) {
  modalVisible.value = true;
  // nextTick解决赋值后重置表单无效问题
  nextTick(() => {
    Object.values(data).length > 0 && setFormData(data);
  });
}

// 表单提交
const handleSubmit = useThrottleFn(() => {
  formRef.value?.validate((valid: boolean) => {
    if (valid) {
      if (typeof props.modalConfig.beforeSubmit === "function") {
        props.modalConfig.beforeSubmit(formData);
      }
      props.modalConfig.formAction(formData).then(() => {
        let msg = "操作成功";
        if (props.modalConfig.component === "drawer") {
          if (props.modalConfig.drawer?.title) {
            msg = `${props.modalConfig.drawer?.title}成功`;
          }
        } else {
          if (props.modalConfig.dialog?.title) {
            msg = `${props.modalConfig.dialog?.title}成功`;
          }
        }
        ElMessage.success(msg);
        emit("submitClick");
        handleClose();
      });
    }
  });
}, 3000);

// 隐藏弹窗
function handleClose() {
  modalVisible.value = false;
}

// 关闭弹窗
function handleCloseModal() {
  formRef.value?.resetFields();
  nextTick(() => {
    formRef.value?.clearValidate();
  });
}

// 禁用表单--用于详情时候用
function handleDisabled(disable: boolean) {
  formDisable.value = disable;
  props.modalConfig.formItems.forEach((item) => {
    if (item) {
      if (item.attrs) {
        item.attrs.disabled = disable;
      } else {
        item.attrs = { disabled: disable };
      }
    }
  });
}

// 暴露的属性和方法
defineExpose({
  setModalVisible,
  getFormData,
  setFormData,
  setFormItemData,
  handleDisabled,
  handleClose,
});
</script>

<style lang="scss" scoped>
h3 {
  color: rgb(63, 158, 255);
}
</style>
