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

import type { SkillCreateIntent } from './skill-create';
import type { SkillCategory, SkillInfo } from './types';

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

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

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

import { saveSkill } from './api';
import { resolveSkillApiErrorMessage } from './skill-api-error';
import { flattenSkillCategories } from './skill-category';
import { buildInitialSkillDraft } from './skill-create';

const props = withDefaults(
  defineProps<{
    canPublish?: boolean;
    categories: SkillCategory[];
    categoriesLoading?: boolean;
    defaultCategoryId?: number | string;
    modelValue: boolean;
  }>(),
  {
    canPublish: false,
    categoriesLoading: false,
    defaultCategoryId: '',
  },
);

const emit = defineEmits<{
  created: [payload: { intent: SkillCreateIntent; 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({
  categoryId: '' as number | string,
  displayName: '',
  intent: 'DRAFT' as SkillCreateIntent,
  visibilityScope: 'PRIVATE',
});

const dialogVisible = computed({
  get: () => props.modelValue,
  set: (value) => {
    if (!value && saving.value) {
      ElMessage.info('请等待当前操作完成');
      return;
    }
    emit('update:modelValue', value);
  },
});
const categoryOptions = computed(() =>
  flattenSkillCategories(props.categories),
);
const rules: FormRules = {
  displayName: [
    { message: '请输入 Skill 名称', required: true, trigger: 'blur' },
    {
      max: 128,
      message: 'Skill 名称不能超过 128 个字符',
      trigger: 'blur',
    },
  ],
};

function resetForm() {
  Object.assign(form, {
    categoryId: props.defaultCategoryId || '',
    displayName: '',
    intent: 'DRAFT',
    visibilityScope: 'PRIVATE',
  });
  actionError.value = '';
  formRef.value?.clearValidate();
  void nextTick(() => nameInputRef.value?.focus());
}

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

  saving.value = true;
  actionError.value = '';
  try {
    const response = await saveSkill(
      buildInitialSkillDraft({
        categoryId: form.categoryId || undefined,
        displayName: form.displayName,
        visibilityScope: form.visibilityScope,
      }),
    );
    if (response.errorCode !== 0 || !response.data?.id) {
      actionError.value = response.message || 'Skill 创建失败，请重试';
      return;
    }
    ElMessage.success('Skill 已创建');
    emit('update:modelValue', false);
    emit('created', { intent: form.intent, skill: response.data });
  } catch (error) {
    actionError.value = resolveSkillApiErrorMessage(
      error,
      'Skill 创建失败，请重试',
    );
  } 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="新建 Skill"
    @confirm="submit"
  >
    <ElForm
      ref="formRef"
      class="skill-create-form easyflow-modal-form easyflow-modal-form--compact"
      label-position="top"
      :model="form"
      :rules="rules"
    >
      <ElAlert
        v-if="actionError"
        class="skill-create-form__alert"
        :closable="false"
        :title="actionError"
        type="error"
        show-icon
      />

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

      <ElFormItem label="分类">
        <ElSelect
          v-model="form.categoryId"
          clearable
          :loading="categoriesLoading"
          placeholder="未分类"
        >
          <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>
      </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-create-form__publish-field">
          <ElRadioGroup v-model="form.intent">
            <ElRadioButton value="DRAFT">草稿</ElRadioButton>
            <ElRadioButton value="PUBLISH" :disabled="!canPublish">
              创建后发布
            </ElRadioButton>
          </ElRadioGroup>
          <span v-if="form.intent === 'PUBLISH'">
            进入详情完善内容，通过校验后提交发布。
          </span>
        </div>
      </ElFormItem>
    </ElForm>
  </EasyFlowFormModal>
</template>

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

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

.skill-create-form__publish-field {
  display: grid;
  gap: var(--space-2);
}

.skill-create-form__publish-field > span {
  font-size: 12px;
  line-height: 1.5;
  color: hsl(var(--text-muted));
}
</style>
