{% import "frontend/page/_macros.j2" as ui %}
<template>
{% if form_container.use_drawer %}
  <ElDrawer
    v-model="visible"
    :title="panelMode === 'add' ? '新增{{ table.subject_label }}' : '编辑{{ table.subject_label }}'"
    size="{{ form_container.size }}"
    destroy-on-close
    @close="handleClose"
  >
{% else %}
  <ElDialog
    v-model="visible"
    :title="panelMode === 'add' ? '新增{{ table.subject_label }}' : '编辑{{ table.subject_label }}'"
    width="{{ form_container.size }}"
    align-center
    @close="handleClose"
  >
{% endif %}
    <ElForm ref="formRef" :model="form" :rules="rules" label-width="120px" v-loading="detailLoading">
      <ElRow :gutter="16">
{% for field in form_fields %}
        <ElCol
{% if field.form_visibility == "add_only" %}
          v-if="panelMode === 'add'"
{% elif field.form_visibility == "edit_only" %}
          v-if="panelMode === 'edit'"
{% endif %}
          :span="{{ field.form_span or 24 }}"
        >
      <ElFormItem
        label="{{ field.label }}"
        prop="{{ field.camel_name }}"
      >
{% if field.form_widget == "textarea" %}
        <ElInput
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "type: 'textarea'"
          ] + (["rows: 3"] if not field.form_props_has_rows else []) + [
            "placeholder: '" ~ field.form_placeholder ~ "'"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "switch" %}
        <ElSwitch
          v-model="form.{{ field.camel_name }}"
{% if field.form_props_literal %}          {{ ui.spread_bind(field.form_props_literal) }}
{% endif %}
        />
{% elif field.form_widget == "select" %}
        <ElSelect
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "placeholder: '" ~ field.form_placeholder ~ "'",
            "clearable: true"
          ], field.form_props_literal, '            ', '          ') }}
        >
          <ElOption
            v-for="item in {{ field.option_items_literal }}"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </ElSelect>
{% elif field.form_widget == "radio_group" %}
        <ElRadioGroup
          v-model="form.{{ field.camel_name }}"
{% if field.form_props_literal %}          {{ ui.spread_bind(field.form_props_literal) }}
{% endif %}
        >
          <ElRadio
            v-for="item in {{ field.option_items_literal }}"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </ElRadioGroup>
{% elif field.form_widget == "checkbox_group" %}
        <ElCheckboxGroup
          v-model="form.{{ field.camel_name }}"
{% if field.form_props_literal %}          {{ ui.spread_bind(field.form_props_literal) }}
{% endif %}
        >
          <ElCheckbox
            v-for="item in {{ field.option_items_literal }}"
            :key="item.value"
            :label="item.label"
            :value="item.value"
          />
        </ElCheckboxGroup>
{% elif field.form_widget == "cascader" %}
        <ElCascader
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "placeholder: '" ~ field.form_placeholder ~ "'",
            "clearable: true",
            "style: { width: '100%' }",
            "options: " ~ field.option_items_literal
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "tree_select" %}
        <ElTreeSelect
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "placeholder: '" ~ field.form_placeholder ~ "'",
            "clearable: true",
            "style: { width: '100%' }",
            "data: " ~ field.option_items_literal
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "input_number" %}
        <ElInputNumber
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "controls: false",
            "style: { width: '100%' }",
            "placeholder: '" ~ field.form_placeholder ~ "'"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "date" %}
        <ElDatePicker
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "type: 'date'",
            "valueFormat: 'YYYY-MM-DD'",
            "placeholder: '" ~ field.form_placeholder ~ "'",
            "style: { width: '100%' }"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "time" %}
        <ElTimePicker
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "valueFormat: 'HH:mm:ss'",
            "placeholder: '" ~ field.form_placeholder ~ "'",
            "style: { width: '100%' }"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "date_time" %}
        <ElDatePicker
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "type: 'datetime'",
            "valueFormat: 'YYYY-MM-DDTHH:mm:ss'",
            "placeholder: '" ~ field.form_placeholder ~ "'",
            "style: { width: '100%' }"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "password" %}
        <ElInput
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "type: 'password'",
            "showPassword: true",
            "placeholder: '" ~ field.form_placeholder ~ "'"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "editor" %}
        <ArtWangEditor
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "placeholder: '" ~ field.form_placeholder ~ "'"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% elif field.form_widget == "image_upload" %}
        <div class="w-full flex flex-col gap-3">
          <ElImage
            v-if="form.{{ field.camel_name }}{% if field.semantic_kind == "avatar" %} || defaultAvatar{% endif %}"
            class="size-20 rounded-md border border-[var(--el-border-color-light)]"
            :src="form.{{ field.camel_name }}{% if field.semantic_kind == "avatar" %} || defaultAvatar{% endif %}"
            fit="cover"
            :preview-src-list="form.{{ field.camel_name }} ? [form.{{ field.camel_name }}] : undefined"
            preview-teleported
          />
          <div class="flex items-center gap-3">
            <ArtFileUpload
              ref="{{ field.camel_name }}UploadRef"
              v-model="{{ field.camel_name }}UploadFiles"
              v-bind="{
{% if field.form_upload_accept %}
                accept: '{{ field.form_upload_accept }}',
{% endif %}
                maxCount: 1,
                showFileList: false,
{% if field.form_upload_button_text %}
                buttonText: '{{ field.form_upload_button_text }}'{% if field.form_upload_props_literal %},
{% endif %}
{% endif %}
{% if field.form_upload_props_literal %}
                {{ ui.object_entries(field.form_upload_props_literal) }}
{% endif %}
              }"
              @upload-success="handle{{ field.pascal_name }}UploadSuccess"
            />
            <ElButton
              v-if="form.{{ field.camel_name }}"
              type="danger"
              link
              @click="clear{{ field.pascal_name }}Upload"
            >
              清除{{ field.label }}
            </ElButton>
          </div>
        </div>
{% elif field.form_widget == "file_upload" %}
        <div class="w-full flex flex-col gap-3">
          <ElLink
            v-if="form.{{ field.camel_name }}"
            :href="form.{{ field.camel_name }}"
            target="_blank"
            type="primary"
          >
            {{ "{{" }} form.{{ field.camel_name }} {{ "}}" }}
          </ElLink>
          <div class="flex items-center gap-3">
            <ArtFileUpload
              ref="{{ field.camel_name }}UploadRef"
              v-model="{{ field.camel_name }}UploadFiles"
              v-bind="{
                maxCount: 1,
                showFileList: false,
{% if field.form_upload_button_text %}
                buttonText: '{{ field.form_upload_button_text }}'{% if field.form_upload_props_literal %},
{% endif %}
{% endif %}
{% if field.form_upload_props_literal %}
                {{ ui.object_entries(field.form_upload_props_literal) }}
{% endif %}
              }"
              @upload-success="handle{{ field.pascal_name }}UploadSuccess"
            />
            <ElButton
              v-if="form.{{ field.camel_name }}"
              type="danger"
              link
              @click="clear{{ field.pascal_name }}Upload"
            >
              清除{{ field.label }}
            </ElButton>
          </div>
        </div>
{% else %}
        <ElInput
          v-model="form.{{ field.camel_name }}"
          {{ ui.vue_bind([
            "placeholder: '" ~ field.form_placeholder ~ "'"
          ], field.form_props_literal, '            ', '          ') }}
        />
{% endif %}
      </ElFormItem>
        </ElCol>
{% endfor %}
      </ElRow>
    </ElForm>
    <template #footer>
      <ElButton @click="handleClose">取消</ElButton>
      <ElButton type="primary" :loading="submitLoading" @click="handleSubmit">提交</ElButton>
    </template>
{% if form_container.use_drawer %}
  </ElDrawer>
{% else %}
  </ElDialog>
{% endif %}
</template>

<script setup lang="ts">
  import { {{ api.fetch_create_fn }}, {{ api.fetch_detail_fn }}, {{ api.fetch_update_fn }} } from '{{ api.import_path }}'
  import type { {{ page.list_item_alias }}, {{ page.list_item_alias }}Detail, FormModel } from '../types'
  import type { FormInstance, FormRules } from 'element-plus'
  import { ElMessage } from 'element-plus'
{% if flags.uses_form_dict %}
  import { useDict } from '@/utils/dict'
{% endif %}
{% if flags.uses_form_upload %}
  import ArtFileUpload from '@/components/core/forms/art-file-upload/index.vue'
{% endif %}
{% if flags.uses_form_editor %}
  import ArtWangEditor from '@/components/core/forms/art-wang-editor/index.vue'
{% endif %}
{% if flags.uses_avatar_placeholder %}
  import defaultAvatar from '@imgs/user/avatar.webp'
{% endif %}

  interface Props {
    modelValue: boolean
    panelMode: 'add' | 'edit'
    {{ page.item_prop_name }}?: {{ page.list_item_alias }}
  }

  interface Emits {
    (e: 'update:modelValue', value: boolean): void
    (e: 'success'): void
  }

  type PanelWatchState = [boolean, Props['panelMode'], {{ page.list_item_alias }}['{{ primary_key.camel_name }}'] | null]

  const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    panelMode: 'add',
    {{ page.item_prop_name }}: undefined
  })

  const emit = defineEmits<Emits>()

{% if flags.uses_form_dict %}
  const { getDict } = useDict()
{% endif %}
{% if flags.uses_form_upload %}
{% for field in form_fields if field.form_widget == "image_upload" or field.form_widget == "file_upload" %}
  const {{ field.camel_name }}UploadRef = ref()
  const {{ field.camel_name }}UploadFiles = ref<Api.FileUpload.FileUploadVo[]>([])
{% endfor %}
{% endif %}
  const formRef = ref<FormInstance>()
  const submitLoading = ref(false)
  const detailLoading = ref(false)

  const visible = computed({
    get: () => props.modelValue,
    set: (value: boolean) => emit('update:modelValue', value)
  })

  const createDefaultForm = (): FormModel => ({
{% for field in form_fields %}
    {{ field.camel_name }}: {{ field.form_default_value }},
{% endfor %}
  })

  const form = reactive<FormModel>(createDefaultForm())

  const rules = reactive<FormRules>({
{% for field in form_fields if field.form_required %}
    {{ field.camel_name }}: [{ required: true, message: '{{ field.form_placeholder }}', trigger: '{{ field.form_rule_trigger }}' }],
{% endfor %}
  })

{% if flags.uses_form_datetime_normalizer %}
  const normalizeDateTimeValue = (value?: string | null) => {
    if (!value) return undefined
    return value.includes('T') ? value : value.replace(' ', 'T')
  }
{% endif %}
{% if flags.uses_form_upload %}
  const resetUploadState = () => {
{% for field in form_fields if field.form_widget == "image_upload" or field.form_widget == "file_upload" %}
    {{ field.camel_name }}UploadFiles.value = []
    {{ field.camel_name }}UploadRef.value?.clear?.()
{% endfor %}
  }

{% for field in form_fields if field.form_widget == "image_upload" or field.form_widget == "file_upload" %}
  const handle{{ field.pascal_name }}UploadSuccess = (file: Api.FileUpload.FileUploadVo) => {
    form.{{ field.camel_name }} = file.url
    {{ field.camel_name }}UploadFiles.value = [file]
  }

  const clear{{ field.pascal_name }}Upload = () => {
    form.{{ field.camel_name }} = {{ field.form_default_value }}
    {{ field.camel_name }}UploadFiles.value = []
    {{ field.camel_name }}UploadRef.value?.clear?.()
  }
{% endfor %}
{% endif %}
  const resetForm = () => {
    Object.assign(form, createDefaultForm())
{% if flags.uses_form_upload %}
    resetUploadState()
{% endif %}
    formRef.value?.clearValidate()
  }

  const initForm = async () => {
    if (props.panelMode === 'edit' && props.{{ page.item_prop_name }}) {
{% if flags.uses_form_upload %}
      resetUploadState()
{% endif %}
      Object.assign(form, {
{% for field in form_fields %}
{% if field.type_info.value_kind == "date_time" %}
        {{ field.camel_name }}: normalizeDateTimeValue(props.{{ page.item_prop_name }}?.{{ field.camel_name }}) ?? {{ field.form_default_value }},
{% else %}
        {{ field.camel_name }}: props.{{ page.item_prop_name }}?.{{ field.camel_name }} ?? {{ field.form_default_value }},
{% endif %}
{% endfor %}
      })
      const id = props.{{ page.item_prop_name }}?.{{ primary_key.camel_name }}
      if (id != null) {
        detailLoading.value = true
        try {
          const detail: {{ page.list_item_alias }}Detail = await {{ api.fetch_detail_fn }}(id)
          Object.assign(form, {
{% for field in form_fields %}
{% if field.type_info.value_kind == "date_time" %}
            {{ field.camel_name }}: normalizeDateTimeValue(detail.{{ field.camel_name }}) ?? form.{{ field.camel_name }},
{% else %}
            {{ field.camel_name }}: detail.{{ field.camel_name }} ?? form.{{ field.camel_name }},
{% endif %}
{% endfor %}
          })
        } finally {
          detailLoading.value = false
        }
      }
    } else {
      resetForm()
    }
  }

  watch(
    (): PanelWatchState => [
      props.modelValue,
      props.panelMode,
      props.{{ page.item_prop_name }}?.{{ primary_key.camel_name }} ?? null
    ],
    async ([visible]: PanelWatchState) => {
      if (visible) {
        await initForm()
        nextTick(() => {
          formRef.value?.clearValidate()
        })
      }
    },
    { immediate: true }
  )

  const handleClose = () => {
    visible.value = false
    resetForm()
  }

  const handleSubmit = async () => {
    if (!formRef.value) return

    try {
      await formRef.value.validate()
    } catch {
      return
    }

    submitLoading.value = true
    try {
      if (props.panelMode === 'add') {
        const payload: Api.{{ api.namespace }}.{{ api.create_params_type_name }} = {
{% for field in form_fields if field.form_visibility != "edit_only" %}
          {{ field.camel_name }}: {{ field.create_submit_value }},
{% endfor %}
        }
        await {{ api.fetch_create_fn }}(payload)
      } else {
        const id = props.{{ page.item_prop_name }}?.{{ primary_key.camel_name }}
        if (id == null) return

        const payload: Api.{{ api.namespace }}.{{ api.update_params_type_name }} = {
{% for field in form_fields if field.form_visibility != "add_only" %}
          {{ field.camel_name }}: {{ field.update_submit_value }},
{% endfor %}
        }
        await {{ api.fetch_update_fn }}(id, payload)
      }

      ElMessage.success(props.panelMode === 'add' ? '新增成功' : '更新成功')
      emit('success')
      handleClose()
    } finally {
      submitLoading.value = false
    }
  }
</script>
