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

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

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

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

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

import { updateSkill } from './api';
import { resolveSkillApiErrorMessage } from './skill-api-error';
import { flattenSkillCategories } from './skill-category';

const props = withDefaults(
  defineProps<{
    categories: SkillCategory[];
    categoriesLoading?: boolean;
    categoryLoadError?: string;
    modelValue: boolean;
    skill: SkillInfo;
  }>(),
  { categoriesLoading: false, categoryLoadError: '' },
);

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

const formRef = ref<FormInstance>();
const nameInputRef = ref<InstanceType<typeof ElInput>>();
const saving = ref(false);
const actionError = ref('');
const form = reactive<SkillInfo>({});
const categoryOptions = computed(() =>
  flattenSkillCategories(props.categories),
);
const currentCategoryAvailable = computed(() =>
  categoryOptions.value.some(
    (category) => String(category.id) === String(form.categoryId),
  ),
);
const dialogVisible = computed({
  get: () => props.modelValue,
  set: (value) => {
    if (!value && saving.value) {
      ElMessage.info('请等待当前操作完成');
      return;
    }
    emit('update:modelValue', value);
  },
});
const rules: FormRules = {
  displayName: [
    { message: '请输入 Skill 名称', required: true, trigger: 'blur' },
    {
      max: 128,
      message: 'Skill 名称不能超过 128 个字符',
      trigger: 'blur',
    },
  ],
};

function resetForm() {
  Object.assign(form, {
    categoryId: props.skill.categoryId || '',
    categoryName: props.skill.categoryName,
    displayName: props.skill.displayName || '',
    enabled: props.skill.enabled !== false,
    id: props.skill.id,
    visibilityScope: props.skill.visibilityScope || 'PRIVATE',
  });
  actionError.value = '';
  formRef.value?.clearValidate();
  void nextTick(() => nameInputRef.value?.focus());
}

async function submit() {
  if (saving.value || props.categoriesLoading) return;
  form.displayName = String(form.displayName || '').trim();
  if (!(await formRef.value?.validate().catch(() => false))) return;

  saving.value = true;
  actionError.value = '';
  try {
    const response = await updateSkill(form);
    if (response.errorCode !== 0) {
      actionError.value = response.message || '设置保存失败，请重试';
      return;
    }
    ElMessage.success('基本信息已保存');
    emit('update:modelValue', false);
    emit('saved', response.data);
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(
      error,
      '设置保存失败，请重试',
    );
  } finally {
    saving.value = false;
  }
}

watch(
  () => props.modelValue,
  (visible) => {
    if (visible) resetForm();
  },
  { immediate: true },
);
</script>

<template>
  <EasyFlowFormModal
    v-model:open="dialogVisible"
    width="520px"
    :closable="!saving"
    :confirm-loading="saving"
    confirm-text="保存"
    :submitting="saving || categoriesLoading"
    title="编辑基本信息"
    @confirm="submit"
  >
    <ElForm
      ref="formRef"
      class="skill-settings-form easyflow-modal-form easyflow-modal-form--compact"
      label-position="top"
      :model="form"
      :rules="rules"
    >
      <ElAlert
        v-if="actionError"
        class="skill-settings-form__alert"
        :closable="false"
        :title="actionError"
        type="error"
        show-icon
      />

      <ElFormItem label="Skill 名称" prop="displayName">
        <ElInput
          ref="nameInputRef"
          v-model="form.displayName"
          maxlength="128"
          show-word-limit
          @keyup.enter="submit"
        />
      </ElFormItem>

      <ElFormItem label="分类">
        <div class="skill-settings-form__category-field">
          <ElSelect
            v-model="form.categoryId"
            clearable
            :disabled="Boolean(categoryLoadError)"
            :loading="categoriesLoading"
            :placeholder="categoryLoadError ? '分类加载失败' : '未分类'"
          >
            <ElOption
              v-if="form.categoryId && !currentCategoryAvailable"
              :label="form.categoryName || '当前分类不可用'"
              :value="form.categoryId"
              disabled
            />
            <ElOption
              v-for="category in categoryOptions"
              :key="category.id"
              :label="`${'\u00a0\u00a0'.repeat(category.depth)}${category.categoryName}`"
              :value="category.id"
              :disabled="category.status !== 1"
            />
          </ElSelect>
          <ElButton
            v-if="categoryLoadError"
            link
            type="primary"
            :loading="categoriesLoading"
            @click="emit('retryCategories')"
          >
            重新加载
          </ElButton>
        </div>
      </ElFormItem>

      <ElFormItem label="可见范围">
        <ElSelect v-model="form.visibilityScope">
          <ElOption label="仅自己" value="PRIVATE" />
          <ElOption label="本部门" value="DEPT" />
          <ElOption label="全员可见" value="PUBLIC" />
        </ElSelect>
      </ElFormItem>

      <ElFormItem label="启用状态">
        <div class="skill-settings-form__switch">
          <ElSwitch v-model="form.enabled" />
          <span>{{ form.enabled === false ? '停用' : '启用' }}</span>
        </div>
      </ElFormItem>
    </ElForm>
  </EasyFlowFormModal>
</template>

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

.skill-settings-form :deep(.el-select) {
  width: 100%;
}

.skill-settings-form__category-field,
.skill-settings-form__switch {
  display: flex;
  gap: var(--space-2);
  align-items: center;
  width: 100%;
}

.skill-settings-form__category-field :deep(.el-select) {
  flex: 1;
  min-width: 0;
}

.skill-settings-form__switch {
  color: hsl(var(--text-muted));
}
</style>
