<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import { commonStatusOptions } from '@/constants/business';
import { fetchCreateDept, fetchUpdateDept } 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: 'UserOrgOperateDialog' });

interface Props {
  operateType: UI.TableOperateType;
  rowData?: Api.SystemManage.Dept | null;
  parentId?: number | null;
  deptTree: Api.SystemManage.Dept[];
  orgCodeOptions: Api.Dict.DictData[];
}

const props = defineProps<Props>();

interface Emits {
  (e: 'submitted', deptId: number): void;
}

const emit = defineEmits<Emits>();

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

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

const submitting = ref(false);

const isEdit = computed(() => props.operateType === 'edit');

const title = computed(() => {
  if (isEdit.value) {
    return $t('page.system.user.editOrg');
  }

  return props.parentId && props.parentId > 0 ? $t('page.system.user.addChildOrg') : $t('page.system.user.addOrg');
});

const orgTypeOptions: CommonType.Option<Api.SystemManage.DeptOrgType, App.I18n.I18nKey>[] = [
  { value: 'company', label: 'page.system.user.orgType.company' },
  { value: 'dept', label: 'page.system.user.orgType.dept' },
  { value: 'function', label: 'page.system.user.orgType.function' },
  { value: 'direction', label: 'page.system.user.orgType.direction' },
  { value: 'team', label: 'page.system.user.orgType.team' }
];

type Model = Api.SystemManage.SaveDeptParams;

const model = ref<Model>(createDefaultModel());

const treeProps = {
  value: 'id',
  label: 'name',
  children: 'children'
} as const;

const parentTree = computed(() => {
  const filteredTree = filterDeptTree(props.deptTree, props.rowData?.id ?? null);

  return [
    {
      id: 0,
      name: $t('page.system.user.topLevelOrg'),
      parentId: -1,
      orgType: 'company' as const,
      status: 0,
      children: filteredTree
    }
  ];
});

const expandParentTree = computed(() => !isEdit.value && (props.parentId ?? 0) === 0);

// 只有组(direction)类型的组织才可以选择编码
const isCodeSelectable = computed(() => {
  return model.value.orgType === 'direction';
});

const rules = {
  name: createRequiredRule($t('page.system.user.form.orgName')),
  parentId: createRequiredRule($t('page.system.user.form.parentOrg')),
  orgType: createRequiredRule($t('page.system.user.form.orgTypeLabel')),
  sort: createRequiredRule($t('page.system.user.form.orgSort')),
  status: createRequiredRule($t('page.system.user.form.userStatus'))
} satisfies Partial<Record<keyof Model, App.Global.FormRule>>;

function createDefaultModel(): Model {
  return {
    name: '',
    parentId: props.parentId ?? 0,
    orgType: 'dept',
    code: '',
    sort: 0,
    status: 0
  };
}

function filterDeptTree(tree: Api.SystemManage.Dept[], excludedId: number | null): Api.SystemManage.Dept[] {
  if (!excludedId) {
    return tree;
  }

  return tree
    .filter(item => item.id !== excludedId)
    .map(item => ({
      ...item,
      children: item.children ? filterDeptTree(item.children, excludedId) : item.children
    }));
}

function initModel() {
  if (isEdit.value && props.rowData) {
    model.value = {
      name: props.rowData.name,
      parentId: props.rowData.parentId,
      orgType: props.rowData.orgType,
      code: props.rowData.code ?? '',
      sort: props.rowData.sort ?? 0,
      status: props.rowData.status
    };
    return;
  }

  model.value = createDefaultModel();
}

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

async function handleSubmit() {
  await validate();

  submitting.value = true;

  const payload: Api.SystemManage.SaveDeptParams = {
    name: model.value.name.trim(),
    parentId: model.value.parentId,
    orgType: model.value.orgType,
    code: String(model.value.code ?? '').trim() || null,
    sort: model.value.sort,
    status: model.value.status
  } as Api.SystemManage.SaveDeptParams;

  if (isEdit.value && props.rowData) {
    const { error } = await fetchUpdateDept({
      id: props.rowData.id,
      ...payload
    });

    submitting.value = false;

    if (error) {
      return;
    }

    window.$message?.success($t('common.updateSuccess'));
    closeDialog();
    emit('submitted', props.rowData.id);
    return;
  }

  const { error, data } = await fetchCreateDept(payload);

  submitting.value = false;

  if (error) {
    return;
  }

  window.$message?.success($t('common.addSuccess'));
  closeDialog();
  emit('submitted', Number(data));
}

watch(visible, async value => {
  if (!value) {
    return;
  }

  initModel();
  await nextTick();
  formRef.value?.clearValidate();
});
</script>

<template>
  <BusinessFormDialog
    v-model="visible"
    :title="title"
    preset="sm"
    :confirm-loading="submitting"
    :scrollbar="false"
    @confirm="handleSubmit"
  >
    <ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
      <ElRow :gutter="16">
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.user.orgName')" prop="name">
            <ElInput v-model="model.name" :placeholder="$t('page.system.user.form.orgName')" />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.user.deptName')" prop="parentId">
            <ElTreeSelect
              v-model="model.parentId"
              check-strictly
              :data="parentTree"
              :default-expand-all="expandParentTree"
              :props="treeProps"
              :render-after-expand="false"
              :placeholder="$t('page.system.user.form.parentOrg')"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.user.orgTypeLabel')" prop="orgType">
            <ElSelect v-model="model.orgType" :placeholder="$t('page.system.user.form.orgTypeLabel')">
              <ElOption v-for="item in orgTypeOptions" :key="item.value" :label="$t(item.label)" :value="item.value" />
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.user.orgCode')" prop="code">
            <ElSelect v-if="isCodeSelectable" v-model="model.code" clearable filterable placeholder="请选择组织编码">
              <ElOption
                v-for="item in props.orgCodeOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
            <ElInput v-else v-model="model.code" :placeholder="$t('page.system.user.form.orgCode')" />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.user.orgSort')" prop="sort">
            <ElInputNumber
              v-model="model.sort"
              class="w-full"
              :min="0"
              :placeholder="$t('page.system.user.form.orgSort')"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem :label="$t('page.system.user.userStatus')" prop="status">
            <ElRadioGroup v-model="model.status" class="business-form-radio-group">
              <ElRadio v-for="item in commonStatusOptions" :key="item.value" :value="item.value">
                {{ $t(item.label) }}
              </ElRadio>
            </ElRadioGroup>
          </ElFormItem>
        </ElCol>
      </ElRow>
    </ElForm>
  </BusinessFormDialog>
</template>
