<template>
  <u-modal
    v-model:open="open"
    v-bind="attrs"
    :title="title"
    class="u-modal-form"
  >
    <UForm
      ref="formRef"
      v-model:value="value"
      :config="config"
      :size="size"
      :layout="layout"
      :rules="rules"
      :label-col="labelCol"
      :class="formClass"
      :preview="preview"
      @submit="onSubmit"
      @reset="onReset"
      @field-change="onFieldChange"
    >
      <template v-for="(item, key) in slots" :key="key" #[key]="{ data, validate, reset }">
        <slot :name="key" :data="data" :validate="validate" :reset="reset" />
      </template>
    </UForm>
    <template v-if="Object.keys(slots).includes('footer')" #footer>
      <slot name="footer" :validate="validator" :reset="resetFields" />
    </template>
  </u-modal>
</template>

<script setup lang="ts">
import { getCurrentInstance, ref, useAttrs, useSlots, watch } from 'vue';
import UModal from '../modal/UModal.vue';
import type { FieldChange, FormConfig } from './types';
import UForm from './UForm.vue';

const props = withDefaults(
  defineProps<{
    // modal
    open: boolean;
    title?: string;
    footer?: string | null;
    zIndex?: number;
    // form
    value: Record<string, any>;
    config: FormConfig[];
    size?: 'large' | 'small' | 'default';
    labelCol?: {
      span?: number;
      offset?: number;
    };
    // 预览模式
    preview?: boolean;
    layout?: 'horizontal' | 'vertical' | 'inline';
    rules?: object;
    formClass?: string;
  }>(),
  {
    // modal
    open: false,
    zIndex: 1000,
    // form
    config: () => [],
    size: 'default',
    layout: 'horizontal',
    value: () => ({})
  }
);
const slots = useSlots();
const attrs = useAttrs();
const ctx = getCurrentInstance();

const open = ref(props.open);
const title = ref(props.title);

const formRef = ref();
const value = ref(props.value);
const config = ref(props.config);

const validator = (args?: any) => {
  return formRef.value?.validate(args);
};

const resetFields = (args?: any) => {
  return formRef.value?.resetFields(args);
};

const onSubmit = (e: any) => {
  ctx?.emit('submit', e);
};
const onReset = (e: any) => {
  ctx?.emit('reset', e);
};

const onFieldChange = (val: FieldChange) => {
  ctx?.emit(`${val.field}Change`, val);
  ctx?.emit('fieldChange', val);
  ctx?.emit('update:value', val.fields);
};

watch(
  () => props.value,
  () => {
    value.value = props.value;
  },
  {
    deep: true
  }
);
watch(
  () => props.config,
  () => {
    config.value = props.config;
  },
  {
    deep: true
  }
);
watch(
  () => props.open,
  () => {
    open.value = props.open;
  }
);
// 处理点击遮罩触发关闭时，同步更新
watch(
  () => open.value,
  () => {
    ctx?.emit('update:open', open.value);
  }
);
watch(
  () => props.title,
  () => {
    title.value = props.title;
  }
);

defineExpose({
  formRef,
  validate: validator,
  resetFields
});
</script>
