<!-- 配置编辑弹窗 -->
<template>
  <ele-modal
    form
    destroy-on-close
    :width="980"
    v-model="visible"
    :title="isUpdate ? '修改配置' : '添加配置'"
  >
    <el-form
      ref="formRef"
      :model="form"
      :rules="rules"
      label-width="80px"
      @submit.prevent=""
    >
      <el-row>
        <el-col :span="12">
          <el-form-item label="上级" prop="pid">
            <config-select :model-value="form.pid" :group="form.group" disabled/>
          </el-form-item>
          <el-form-item label="类型" prop="type">
            <el-select
              clearable
              class="ele-fluid"
              placeholder="请选择类型"
              v-model="form.type"
              :disabled="form._type_readonly"
            >
              <el-option
                v-for="label in configItemType"
                :value="label"
                :label="getItemLabel(label)"
                :key="label"
              />
            </el-select>
          </el-form-item>
          <el-form-item label="配置标题" prop="title">
            <el-input
              clearable
              :maxlength="20"
              v-model="form.title"
              placeholder="请输入配置标题(一般由中文组成，仅用于显示)"
            />
          </el-form-item>
          <template v-if="form.type">
            <el-form-item
              label="配置名称"
              prop="name"
              v-if="HIDE_FORM_ITEM_WHERE.name()"
            >
              <el-input
                clearable
                :maxlength="20"
                v-model="form.name"
                placeholder="请输入配置名称"
              />
            </el-form-item>
            <el-form-item
              label="配置值"
              v-if="HIDE_FORM_ITEM_WHERE.value()"
            >
              <el-input
                :rows="4"
                type="textarea"
                v-model="form.value"
                placeholder="请输入配置值"
              />
            </el-form-item>
            <el-form-item
              label="配置项"
              v-if="HIDE_FORM_ITEM_WHERE.option()"
            >
              <el-input
                :rows="4"
                type="textarea"
                v-model="form.option"
                placeholder="请输入配置项"
              />
            </el-form-item>

          </template>
        </el-col>
        <el-col :span="11" :offset="1">
          <el-form-item label="BIND" prop="itemBind">
            <el-input
              :rows="4"
              type="textarea"
              v-model="form.itemBind"
              placeholder=""
            />
          </el-form-item>
          <el-form-item label="Class" prop="itemClass">
            <el-input
              type="text"
              v-model="form.itemClass"
              placeholder="请输入渲染框CSS样式类"
            />
          </el-form-item>
          <el-form-item label="Style">
            <el-input
              :rows="4"
              type="textarea"
              v-model="form.itemStyle"
              placeholder="请输入渲染框Style样式"
            />
          </el-form-item>
          <el-card header="样式预览:" style="margin-bottom: 30px;"  v-if="form.type && HIDE_FORM_ITEM_WHERE.preview()">
            <config-form-item
              :name="preview.name"
              :title="preview.title"
              :type="preview.type"
              :value="preview.value"
              :option="preview.option"
              :item-bind="preview.bind"
              :key="preview.id"
            />
            <el-form-item v-if="preview.tips">
              <ele-text type="placeholder" style="line-height: 1.6">
                {{ preview.tips }}
              </ele-text>
            </el-form-item>
          </el-card>
        </el-col>
      </el-row>
      <el-form-item label="配置说明" v-if="HIDE_FORM_ITEM_WHERE.tips()">
        <el-input
          type="textarea"
          v-model="form.tips"
          placeholder="请输入配置说明(在配置页简短提示作用)"
        />
      </el-form-item>
      <el-divider/>
      <el-form-item label="备注">
        <el-input
          type="textarea"
          v-model="form.comments"
          placeholder="请输入备注(详细描述此配置的功能和作用) - 此备注仅开发人员可见"
        />
      </el-form-item>
    </el-form>
    <template #footer>
      <el-button @click="handleCancel">取消</el-button>
      <el-button type="primary" :loading="loading" @click="save">
        保存
      </el-button>
    </template>
  </ele-modal>
</template>

<script lang="ts" setup>
import {ref, watch, computed} from 'vue';
import type {FormInstance, FormRules} from 'element-plus';
import {EleMessage} from 'ele-admin-plus';
import {useFormData} from '@/utils/use-form-data';
import type {Config} from '@/api/system/config/model';
import {addConfig, updateConfig, checkExistence} from '@/api/system/config';
import ConfigSelect from './config-select.vue';
import {ItemType, getItemLabel} from '@/enum/config-item-type.ts';
import ConfigFormItem from "@/views/system/config-set/components/config-form-item.vue";
import {strToBind, strToOption} from "@/utils/sys-config";

const HIDE_FORM_ITEM_WHERE: any = {
  name: () => {
    return ['tabs', 'tabs_item', 'alert', 'card', 'separator'].indexOf(<string>form.type) == -1;
  },
  value: () => {
    return ['tabs', 'tabs_item'].indexOf(<string>form.type) == -1
  },
  option: () => {
    return ['tabs', 'tabs_item'].indexOf(<string>form.type) == -1
  },
  tips: () => {
    return ['separator', 'alert', 'card', 'collapse','tabs'].indexOf(<string>form.type) == -1
  },
  preview: ()=>{
    return ['tabs', 'tabs_item','card', 'collapse', 'alert', 'separator','json'].indexOf(<string>form.type) == -1
  }
};
const preview = computed(() => {
  return {
    ...form,
    bind: strToBind(<string>form.type, <string>form.itemBind),
    option: strToOption(<string>form.type, <string>form.option)
  }
})
const configItemType: any = computed(() => {
  let list = {};
  if (props.parent) {
    if (props.parent.type == 'tabs') {
      list[ItemType.TABS_ITEM] = ItemType.TABS_ITEM;
    } else if (props.parent.type == 'tabs_item') {
      for (const name in ItemType) {
        if (
          [ItemType.TABS_ITEM, ItemType.TABS].indexOf(ItemType[name]) == -1
        ) {
          list[name] = ItemType[name];
        }
      }
    }
  }
  if (Object.keys(list).length == 0) {
    return ItemType;
  } else {
    return list;
  }
});
const props = defineProps<{
  /** 修改回显的数据 */
  data?: Config | null;
  /** 父级元素 */
  parent?: Config | null;
  /** 配置所属组 */
  group?: string | null;
}>();

const emit = defineEmits<{
  (e: 'done'): void;
}>();

/** 弹窗是否打开 */
const visible = defineModel({type: Boolean});

/** 是否是修改 */
const isUpdate = ref(false);

/** 提交状态 */
const loading = ref(false);

/** 表单实例 */
const formRef = ref<FormInstance | null>(null);

interface ConfigEdit extends Config {
  _type_readonly: boolean;
}

/** 表单数据 */
const [form, resetFields, assignFields] = useFormData<ConfigEdit>({
  id: void 0,
  pid: 0,
  _type_readonly: false,
  type: '',
  comments: '',
  group: '',
  title: '',
  name: '',
  tips: '',
  option: '',
  value: '',
  itemBind: '',
  itemStyle: '',
  itemClass: ''
});

/** 表单验证规则 */
const rules = computed<FormRules>(() => {
  const obj: FormRules = {
    title: [
      {
        required: true,
        type: 'string',
        message: '请输入标题',
        trigger: 'blur'
      }
    ],
    name: [
      {
        required: true,
        message: '请输入配置名称',
        type: 'string',
        trigger: 'blur'
      },
      {
        type: 'string',
        trigger: 'blur',
        validator: (_rule: any, value: string, callback: any) => {
          checkExistence('name', value, isUpdate.value ? props.data.id : null)
            .then(() => {
              callback(new Error('配置名称已经存在'));
            })
            .catch(() => {
              callback();
            });
        }
      }
    ],
    itemBind: [
      {
        type: 'string',
        validator: (_rule: any, value: string, callback: any) => {
          if (value) {
            const msg = '请输入正确的JSON格式';
            try {
              const obj = JSON.parse(value);
              if (obj == null || typeof obj !== 'object') {
                callback(msg);
                return;
              }
            } catch (_e) {
              callback(msg);
              return;
            }
          }
          callback();
        },
        trigger: 'blur'
      }
    ],

  };
  return obj;
});

/** 关闭弹窗 */
const handleCancel = () => {
  visible.value = false;
};

/** 保存编辑 */
const save = () => {
  formRef.value?.validate?.((valid) => {
    if (!valid) {
      return;
    }
    loading.value = true;
    const saveOrUpdate = isUpdate.value ? updateConfig : addConfig;
    saveOrUpdate(form)
      .then((msg) => {
        loading.value = false;
        EleMessage.success({message: msg, plain: true});
        handleCancel();
        emit('done');
      })
      .catch((e) => {
        loading.value = false;
        EleMessage.error({message: e.message, plain: true});
      });
  });
};

/** 监听弹窗打开 */
watch(visible, () => {
  if (visible.value) {
    if (props.data) {
      assignFields(props.data);
      isUpdate.value = true;
    } else {
      resetFields();
      isUpdate.value = false;
      if (props.parent) {
        let data: any = {pid: props.parent.id};
        if (props.parent.type == 'tabs') {
          data.type = 'tabs_item';
          data._type_readonly = true;
        }
        assignFields(data);
      }
    }
    if (['tabs_item','tabs'].indexOf(form.type) != -1) {
      form._type_readonly = true;
    }
    form.group = props.group;
  }
});
</script>
