<script setup lang="ts">
import type { FormInstance, FormRules } from 'element-plus';

import type { SkillCategory, SkillCategoryDraft } from './types';

import { computed, nextTick, reactive, ref, watch } from 'vue';

import { EasyFlowFormModal } from '@easyflow/common-ui';

import {
  ElAlert,
  ElForm,
  ElFormItem,
  ElInput,
  ElInputNumber,
  ElMessage,
  ElOption,
  ElSelect,
  ElSwitch,
} from 'element-plus';

import {
  getSkillCategoryTree,
  saveSkillCategory,
  updateSkillCategory,
} from './api';
import { resolveSkillApiErrorMessage } from './skill-api-error';
import { getSkillCategoryParentOptions } from './skill-category';

const props = defineProps<{
  category?: SkillCategory;
  modelValue: boolean;
}>();

const emit = defineEmits<{
  saved: [];
  'update:modelValue': [value: boolean];
}>();

const formRef = ref<FormInstance>();
const nameInputRef = ref<InstanceType<typeof ElInput>>();
const categories = ref<SkillCategory[]>([]);
const categoriesLoading = ref(false);
const saveLoading = ref(false);
const loadError = ref('');
const actionError = ref('');
const form = reactive<SkillCategoryDraft>({
  categoryName: '',
  parentId: '',
  sortNo: 0,
  status: 1,
});

const dialogVisible = computed({
  get: () => props.modelValue,
  set: (value) => {
    if (!value && saveLoading.value) {
      ElMessage.info('请等待当前操作完成');
      return;
    }
    emit('update:modelValue', value);
  },
});
const parentOptions = computed(() =>
  getSkillCategoryParentOptions(categories.value, form.id),
);
const dialogTitle = computed(() => (form.id ? '编辑分类' : '添加分类'));
const formRules: FormRules = {
  categoryName: [
    { message: '请输入分类名称', required: true, trigger: 'blur' },
    {
      max: 128,
      message: '分类名称不能超过 128 个字符',
      trigger: 'blur',
    },
  ],
};

function resetForm() {
  Object.assign(form, {
    categoryName: props.category?.categoryName || '',
    id: props.category?.id,
    parentId: props.category?.parentId ?? '',
    sortNo: props.category?.sortNo ?? 0,
    status: props.category?.status === 0 ? 0 : 1,
  });
  actionError.value = '';
  formRef.value?.clearValidate();
  void nextTick(() => nameInputRef.value?.focus());
}

async function loadCategories() {
  if (categoriesLoading.value) return;
  categoriesLoading.value = true;
  loadError.value = '';
  try {
    const res = await getSkillCategoryTree();
    if (res.errorCode !== 0) {
      loadError.value = res.message || '分类加载失败，请重试';
      return;
    }
    categories.value = res.data || [];
  } catch (error) {
    loadError.value = resolveSkillApiErrorMessage(
      error,
      '分类加载失败，请重试',
    );
  } finally {
    categoriesLoading.value = false;
  }
}

async function submitCategory() {
  if (saveLoading.value || categoriesLoading.value) return;
  form.categoryName = form.categoryName.trim();
  if (!(await formRef.value?.validate().catch(() => false))) return;

  saveLoading.value = true;
  actionError.value = '';
  const editing = Boolean(form.id);
  try {
    const res = editing
      ? await updateSkillCategory(form)
      : await saveSkillCategory(form);
    if (res.errorCode !== 0) {
      actionError.value = res.message || '分类保存失败，请重试';
      return;
    }
    ElMessage.success(editing ? '分类已更新' : '分类已创建');
    emit('update:modelValue', false);
    emit('saved');
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(
      error,
      '分类保存失败，请重试',
    );
  } finally {
    saveLoading.value = false;
  }
}

watch(
  () => props.modelValue,
  (visible) => {
    if (!visible) return;
    resetForm();
    void loadCategories();
  },
  { immediate: true },
);

watch(
  () => props.category,
  () => {
    if (props.modelValue) resetForm();
  },
);
</script>

<template>
  <EasyFlowFormModal
    v-model:open="dialogVisible"
    width="520px"
    :closable="!saveLoading"
    :confirm-loading="saveLoading"
    confirm-text="保存"
    :submitting="saveLoading || categoriesLoading"
    :title="dialogTitle"
    @confirm="submitCategory"
  >
    <ElForm
      ref="formRef"
      class="skill-category-form easyflow-modal-form easyflow-modal-form--compact"
      label-position="top"
      :model="form"
      :rules="formRules"
    >
      <ElAlert
        v-if="loadError"
        class="skill-category-form__alert"
        :closable="false"
        :title="loadError"
        type="error"
        show-icon
      />
      <ElAlert
        v-if="actionError"
        class="skill-category-form__alert"
        :closable="false"
        :title="actionError"
        type="error"
        show-icon
      />

      <ElFormItem label="分类名称" prop="categoryName">
        <ElInput
          ref="nameInputRef"
          v-model="form.categoryName"
          maxlength="128"
          placeholder="请输入分类名称"
          show-word-limit
          @keyup.enter="submitCategory"
        />
      </ElFormItem>
      <ElFormItem label="上级分类">
        <ElSelect
          v-model="form.parentId"
          clearable
          :loading="categoriesLoading"
          placeholder="无（根分类）"
        >
          <ElOption
            v-for="option in parentOptions"
            :key="option.id"
            :label="`${'\u00a0\u00a0'.repeat(option.depth)}${option.categoryName}`"
            :value="option.id"
            :disabled="option.status === 0"
          />
        </ElSelect>
      </ElFormItem>
      <ElFormItem label="排序">
        <ElInputNumber
          v-model="form.sortNo"
          :max="999_999"
          :min="-999_999"
          controls-position="right"
        />
      </ElFormItem>
      <ElFormItem label="启用">
        <ElSwitch v-model="form.status" :active-value="1" :inactive-value="0" />
      </ElFormItem>
    </ElForm>
  </EasyFlowFormModal>
</template>

<style scoped>
.skill-category-form__alert {
  margin-bottom: var(--space-4);
}

.skill-category-form :deep(.el-select),
.skill-category-form :deep(.el-input-number) {
  width: 100%;
}
</style>
