<template>
  <el-dialog
    v-model="visible"
    :title="dialogType === 'add' ? $t('page.form.titleAdd') : $t('page.form.titleEdit')"
    width="800px"
    align-center
    :close-on-click-modal="false"
    @close="handleClose"
  >
    <el-form ref="formRef" :model="formData" :rules="rules" label-width="100px">
      <el-form-item :label="$t('page.form.labelAvatar')" prop="avatar">
        <sa-image-picker v-model="formData.avatar" round />
      </el-form-item>
      <el-row>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelUsername')" prop="username">
            <el-input v-model="formData.username" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelRealname')" prop="realname">
            <el-input v-model="formData.realname" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row v-if="dialogType === 'add'">
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelPassword')" prop="password">
            <el-input type="password" v-model="formData.password" show-password />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelPasswordConfirm')" prop="password_confirm">
            <el-input type="password" v-model="formData.password_confirm" show-password />
          </el-form-item>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelEmail')" prop="email">
            <el-input v-model="formData.email" :placeholder="$t('page.form.placeholderEmail')" />
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelPhone')" prop="phone">
            <el-input v-model="formData.phone" :placeholder="$t('page.form.placeholderPhone')" />
          </el-form-item>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelDept')" prop="dept_id">
            <el-select v-model="formData.dept_id" clearable filterable>
              <el-option
                v-for="item in optionData.deptData"
                :key="item.id"
                :label="item.label"
                :value="item.id"
              />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelRole')" prop="role_ids">
            <el-select v-model="formData.role_ids" multiple clearable>
              <el-option
                v-for="role in optionData.roleList"
                :key="(role as any)?.id"
                :value="(role as any)?.id"
                :label="(role as any)?.name"
              />
            </el-select>
          </el-form-item>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="12">
          <el-form-item :label="$t('page.form.labelGender')" prop="gender">
            <sa-radio v-model="formData.gender" dict="gender" valueType="string" />
          </el-form-item>
        </el-col>
      </el-row>
      <el-row>
        <el-col :span="24">
          <el-form-item :label="$t('page.form.labelStatus')" prop="status">
            <sa-radio v-model="formData.status" dict="data_status" />
          </el-form-item>
        </el-col>
      </el-row>

      <el-row>
        <el-col :span="24">
          <el-form-item :label="$t('page.form.labelRemark')" prop="remark">
            <el-input
              v-model="formData.remark"
              type="textarea"
              :rows="3"
              :placeholder="$t('page.form.placeholderRemark')"
            />
          </el-form-item>
        </el-col>
      </el-row>
    </el-form>
    <template #footer>
      <div class="dialog-footer">
        <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
        <el-button type="primary" @click="handleSubmit">{{ $t('table.form.submit') }}</el-button>
      </div>
    </template>
  </el-dialog>
</template>

<script setup lang="ts">
  import type { FormInstance, FormRules } from 'element-plus'
  import api from '@/api/system/user'
  import deptApi from '@/api/system/dept'
  import roleApi from '@/api/system/role'
  import { ElMessage } from 'element-plus'
  import { useI18n } from 'vue-i18n'

  interface Props {
    modelValue: boolean
    dialogType: string
    data?: Record<string, any>
  }

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

  const props = withDefaults(defineProps<Props>(), {
    modelValue: false,
    dialogType: 'add',
    data: undefined
  })

  const emit = defineEmits<Emits>()
  const { t } = useI18n()

  const formRef = ref<FormInstance>()
  const optionData = reactive({
    deptData: <any>[],
    roleList: <any>[]
  })

  /**
   * 弹窗显示状态双向绑定
   */
  const visible = computed({
    get: () => props.modelValue,
    set: (value) => emit('update:modelValue', value)
  })

  const validatePasswordConfirm = (rule: any, value: any, callback: any) => {
    if (value !== formData.password) {
      callback(new Error(t('page.form.rulePasswordNotMatch')))
    } else {
      callback()
    }
  }

  // 表单验证规则
  const rules = computed<FormRules>(() => ({
    username: [
      { required: true, message: t('page.form.ruleUsernameRequired'), trigger: 'blur' },
      { min: 2, max: 20, message: t('page.form.ruleUsernameLength'), trigger: 'blur' }
    ],
    password: [
      { required: true, message: t('page.form.rulePasswordRequired'), trigger: 'blur' },
      { min: 6, max: 20, message: t('page.form.rulePasswordLength'), trigger: 'blur' }
    ],
    password_confirm: [
      { required: true, message: t('page.form.rulePasswordConfirmRequired'), trigger: 'blur' },
      { min: 6, max: 20, message: t('page.form.rulePasswordLength'), trigger: 'blur' },
      { validator: validatePasswordConfirm, trigger: 'blur' }
    ],
    dept_id: [{ required: true, message: t('page.form.ruleDeptRequired'), trigger: 'change' }],
    role_ids: [{ required: true, message: t('page.form.ruleRoleRequired'), trigger: 'blur' }]
  }))

  // 初始表单数据
  const initialFormData = {
    id: null,
    avatar: '',
    username: '',
    password: '',
    password_confirm: '',
    realname: '',
    dept_id: '',
    phone: '',
    email: '',
    role_ids: [],
    status: 1,
    gender: '',
    remark: ''
  }

  /**
   * 表单数据
   */
  const formData = reactive({ ...initialFormData })

  /**
   * 监听弹窗打开，初始化表单数据
   */
  const flattenDeptOptions = (list: any[], result: { id: number; label: string }[] = []) => {
    for (const item of list) {
      const id = item.id ?? item.value
      if (id !== undefined && id !== null) {
        result.push({
          id,
          label: String(item.label ?? item.name ?? id)
        })
      }
      if (item.children?.length) {
        flattenDeptOptions(item.children, result)
      }
    }
    return result
  }

  const loadRoleOptions = async () => {
    const deptId = formData.dept_id
    const params =
      deptId !== undefined && deptId !== null && deptId !== ''
        ? { dept_id: deptId }
        : undefined
    const roleData = await roleApi.accessRole(params)
    optionData.roleList = Array.isArray(roleData) ? roleData : []
  }

  watch(
    () => formData.dept_id,
    () => {
      if (props.modelValue) {
        void loadRoleOptions()
      }
    }
  )

  watch(
    () => props.modelValue,
    (newVal) => {
      if (newVal) {
        initPage()
      }
    }
  )

  const initPage = async () => {
    // 先重置为初始值
    Object.assign(formData, initialFormData)
    const deptData = await deptApi.accessDept()
    optionData.deptData = flattenDeptOptions(Array.isArray(deptData) ? deptData : [])
    // 角色数据
    if (props.data?.id) {
      await nextTick()
      const data = await api.read(props.data.id)
      const role = (data.roleList as any[])?.map((item: any) => item.id)
      data.role_ids = role
      data.password = ''
      initForm(data)
      await loadRoleOptions()
    } else {
      await loadRoleOptions()
    }
  }

  /**
   * 初始化表单数据
   */
  const initForm = (data: any) => {
    if (data) {
      for (const key in formData) {
        if (data[key] != null && data[key] != undefined) {
          ;(formData as any)[key] = data[key]
        }
      }
    }
  }

  /**
   * 关闭弹窗并重置表单
   */
  const handleClose = () => {
    visible.value = false
    formRef.value?.resetFields()
  }

  /**
   * 提交表单
   */
  const handleSubmit = async () => {
    if (!formRef.value) return

    try {
      await formRef.value.validate()
      if (props.dialogType === 'add') {
        await api.save(formData)
        ElMessage.success(t('page.form.addSuccess'))
      } else {
        await api.update(formData)
        ElMessage.success(t('page.form.editSuccess'))
      }
      emit('success')
      handleClose()
    } catch (error) {
      console.log('表单验证失败:', error)
    }
  }
</script>
