<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import { commonStatusOptions } from '@/constants/business';
import { postTypeOptions } from '@/constants/business';
import { fetchCreatePost, fetchGetPost, fetchUpdatePost } from '@/service/api';
import { useForm, useFormRules } from '@/hooks/common/form';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import { $t } from '@/locales';

defineOptions({ name: 'PostOperateDialog' });

interface Props {
  operateType: UI.TableOperateType;
  rowData?: Api.SystemManage.Post | null;
}

const props = defineProps<Props>();

const emit = defineEmits<{
  submitted: [postId: number];
}>();

const visible = defineModel<boolean>('visible', {
  default: false
});

const { formRef, validate } = useForm();
const { createRequiredRule } = useFormRules();

const detailLoading = ref(false);
const submitting = ref(false);
const isEdit = computed(() => props.operateType === 'edit');

const title = computed(() => {
  const titleMap: Record<UI.TableOperateType, string> = {
    add: $t('page.system.post.addPost'),
    edit: $t('page.system.post.editPost')
  };

  return titleMap[props.operateType];
});

type Model = Api.SystemManage.SavePostParams;

const model = ref(createDefaultModel());

function createDefaultModel(): Model {
  return {
    name: '',
    code: '',
    postType: null,
    levelRank: null,
    sort: 0,
    status: 0,
    remark: ''
  };
}

const rules = {
  name: createRequiredRule($t('page.system.post.form.postName')),
  code: createRequiredRule($t('page.system.post.form.postCode')),
  postType: createRequiredRule($t('page.system.post.form.postType')),
  sort: createRequiredRule($t('page.system.post.form.sort')),
  status: createRequiredRule($t('page.system.post.form.postStatus'))
} satisfies Record<string, App.Global.FormRule>;

function closeModal() {
  visible.value = false;
}

async function initModel() {
  model.value = createDefaultModel();

  if (!isEdit.value || !props.rowData) {
    await nextTick();
    formRef.value?.clearValidate();
    return;
  }

  detailLoading.value = true;

  const { error, data } = await fetchGetPost(props.rowData.id);

  detailLoading.value = false;

  if (!error) {
    model.value = {
      name: data.name,
      code: data.code ?? '',
      postType: data.postType ?? null,
      levelRank: data.levelRank ?? null,
      sort: data.sort ?? 0,
      status: data.status,
      remark: data.remark ?? ''
    };
  }

  await nextTick();
  formRef.value?.clearValidate();
}

async function handleSubmit() {
  await validate();

  submitting.value = true;

  const submitData: Api.SystemManage.SavePostParams = {
    ...model.value,
    name: model.value.name.trim(),
    code: model.value.code?.trim() || null,
    remark: model.value.remark?.trim() || null
  };

  const request =
    isEdit.value && props.rowData
      ? await fetchUpdatePost({id: props.rowData.id, ...submitData})
      : await fetchCreatePost(submitData);

  const { error, data } = await request;

  submitting.value = false;

  if (error) {
    return;
  }

  const postId = isEdit.value && props.rowData ? props.rowData.id : Number(data);

  window.$message?.success($t(isEdit.value ? 'common.updateSuccess' : 'common.addSuccess'));

  closeModal();
  emit('submitted', postId);
}

watch(visible, value => {
  if (value) {
    initModel();
  }
});
</script>

<template>
  <BusinessFormDialog
    v-model="visible"
    :title="title"
    preset="md"
    :loading="detailLoading"
    :confirm-loading="submitting"
    :scrollbar="false"
    @confirm="handleSubmit"
  >
    <ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
      <ElRow :gutter="16">
        <ElCol :span="12">
          <ElFormItem :label="$t('page.system.post.postName')" prop="name">
            <ElInput v-model="model.name" :placeholder="$t('page.system.post.form.postName')" />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem :label="$t('page.system.post.postCode')" prop="code">
            <ElInput v-model="model.code" :placeholder="$t('page.system.post.form.postCode')" />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem :label="$t('page.system.post.postType')" prop="postType">
            <ElSelect v-model="model.postType" class="w-full" :placeholder="$t('page.system.post.form.postType')">
              <ElOption v-for="{ label, value } in postTypeOptions" :key="value" :label="$t(label)" :value="value" />
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem :label="$t('page.system.post.levelRank')" prop="levelRank">
            <ElInputNumber
              v-model="model.levelRank"
              class="w-full"
              :min="0"
              :placeholder="$t('page.system.post.form.levelRank')"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem :label="$t('page.system.post.sort')" prop="sort">
            <ElInputNumber
              v-model="model.sort"
              class="w-full"
              :min="0"
              :placeholder="$t('page.system.post.form.sort')"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem :label="$t('page.system.post.postStatus')" prop="status">
            <ElRadioGroup v-model="model.status" class="business-form-radio-group">
              <ElRadio v-for="{ label, value } in commonStatusOptions" :key="value" :value="value">
                {{ $t(label) }}
              </ElRadio>
            </ElRadioGroup>
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.post.remark')" prop="remark">
            <ElInput
              v-model="model.remark"
              type="textarea"
              :rows="4"
              :placeholder="$t('page.system.post.form.remark')"
            />
          </ElFormItem>
        </ElCol>
      </ElRow>
    </ElForm>
  </BusinessFormDialog>
</template>

<style scoped></style>
