<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue';
import { fetchCreateRequirement, fetchGetRequirementModuleTree } from '@/service/api';
import { useForm, useFormRules } from '@/hooks/common/form';
import { useDict } from '@/hooks/business/dict';
import BusinessFormDialog from '@/components/custom/business-form-dialog.vue';
import BusinessRichTextEditor from '@/components/custom/business-rich-text-editor.vue';
import DictSelect from '@/components/custom/dict-select.vue';
import MemberSelectOption from './member-select-option.vue';

defineOptions({ name: 'RequirementCreateDialog' });

interface Props {
  productId: string;
  defaultModuleId?: string;
  memberOptions: Api.Product.ProductMember[];
  categoryDictCode: string;
  priorityDictCode: string;
}

const props = defineProps<Props>();

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

const emit = defineEmits<Emits>();

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

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

const { enabledDictData: priorityDictData } = useDict(() => props.priorityDictCode);

const priorityOptions = computed(() => {
  return priorityDictData.value.map(item => ({
    label: item.label,
    value: Number(item.value)
  }));
});

interface Model {
  title: string;
  description: string;
  reviewRequired: number;
  moduleId: string;
  category: string;
  priority: number | null;
  proposerId: string;
  currentHandlerUserId: string;
  workHours: number | null;
  sort: number;
}

const submitting = ref(false);
const loading = ref(false);
const moduleTree = ref<Api.Product.RequirementModule[]>([]);

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

const memberUserOptions = computed(() => {
  return props.memberOptions.filter(m => m.status === 0);
});

const flatModuleOptions = computed<Array<{ label: string; value: string }>>(() => {
  const options: Array<{ label: string; value: string }> = [];

  function walk(modules: Api.Product.RequirementModule[], parentPath: string) {
    for (const module of modules) {
      const currentPath = `${parentPath}/${module.moduleName}`;
      options.push({
        label: currentPath,
        value: module.id || ''
      });
      if (module.children?.length) {
        walk(module.children, currentPath);
      }
    }
  }

  if (moduleTree.value.length > 0) {
    walk(moduleTree.value, '');
  }

  return options;
});

const reviewRequiredOptions = [
  { label: '不需要', value: 0 },
  { label: '需要', value: 1 }
];

const rules = {
  title: [createRequiredRule('请输入需求名称')],
  category: [createRequiredRule('请选择需求类型')],
  priority: [createRequiredRule('请选择优先级')],
  proposerId: [createRequiredRule('请选择提出人')],
  currentHandlerUserId: [createRequiredRule('请选择负责人')],
  workHours: [createRequiredRule('请输入所需工时')]
} satisfies Record<string, App.Global.FormRule[]>;

function createDefaultModel(): Model {
  return {
    title: '',
    description: '',
    reviewRequired: 0,
    moduleId: props.defaultModuleId || '0',
    category: '功能需求',
    priority: 1,
    proposerId: '',
    currentHandlerUserId: '',
    workHours: null,
    sort: 0
  };
}

function getNullableText(value?: string | null) {
  return value?.trim() || null;
}

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

async function handleSubmit() {
  await validate();

  if (!props.productId) {
    return;
  }

  const proposer = memberUserOptions.value.find(m => m.userId === model.value.proposerId);
  const proposerNickname = proposer?.userNickname || '';
  const handler = memberUserOptions.value.find(m => m.userId === model.value.currentHandlerUserId);
  const currentHandlerUserNickname = handler?.userNickname || '';

  const payload: Api.Product.SaveRequirementParams = {
    productId: props.productId,
    moduleId: model.value.moduleId || '0',
    reviewRequired: model.value.reviewRequired as Api.Product.RequirementReviewRequired,
    title: model.value.title.trim(),
    description: getNullableText(model.value.description),
    category: model.value.category,
    priority: Number(model.value.priority) as Api.Product.RequirementPriority,
    proposerId: model.value.proposerId,
    proposerNickname,
    currentHandlerUserId: model.value.currentHandlerUserId,
    currentHandlerUserNickname,
    implementProjectId: null,
    workHours: model.value.workHours || 0,
    sort: model.value.sort
  };

  submitting.value = true;

  const result = await fetchCreateRequirement(payload);

  submitting.value = false;

  if (result.error) {
    return;
  }

  window.$message?.success('需求新增成功');
  closeDialog();
  emit('submitted');
}

async function loadModuleTree() {
  if (!props.productId) {
    moduleTree.value = [];
    return;
  }

  const { error, data } = await fetchGetRequirementModuleTree(props.productId);

  if (error || !data) {
    moduleTree.value = [];
    return;
  }

  moduleTree.value = data;
}

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

    model.value = createDefaultModel();
    await loadModuleTree();

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

<template>
  <BusinessFormDialog
    v-model="visible"
    title="新增需求"
    preset="lg"
    :loading="loading"
    :confirm-loading="submitting"
    @confirm="handleSubmit"
  >
    <ElForm ref="formRef" :model="model" :rules="rules" label-position="top">
      <ElRow :gutter="16">
        <ElCol :span="12">
          <ElFormItem label="需求名称" prop="title">
            <ElInput v-model="model.title" clearable maxlength="256" placeholder="请输入需求名称" />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="模块">
            <ElSelect v-model="model.moduleId" class="w-full" filterable placeholder="请选择所属模块">
              <ElOption v-for="item in flatModuleOptions" :key="item.value" :label="item.label" :value="item.value" />
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="24">
          <ElFormItem label="内容">
            <BusinessRichTextEditor
              v-model="model.description"
              height="240px"
              upload-directory="requirement"
              placeholder="请输入需求内容"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="是否需要评审">
            <ElSelect v-model="model.reviewRequired" class="w-full" placeholder="请选择">
              <ElOption
                v-for="item in reviewRequiredOptions"
                :key="item.value"
                :label="item.label"
                :value="item.value"
              />
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="优先级" prop="priority">
            <ElSelect v-model="model.priority" class="w-full" filterable placeholder="请选择优先级">
              <ElOption v-for="item in priorityOptions" :key="item.value" :label="item.label" :value="item.value" />
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="所需工时" prop="workHours">
            <ElInputNumber
              v-model="model.workHours"
              class="w-full"
              :min="0"
              :max="9999"
              :precision="1"
              placeholder="请输入所需工时"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="需求类型" prop="category">
            <DictSelect
              v-model="model.category"
              :dict-code="categoryDictCode"
              filterable
              placeholder="请选择需求类型"
            />
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="提出人" prop="proposerId">
            <ElSelect v-model="model.proposerId" class="w-full" filterable placeholder="请选择提出人">
              <ElOption
                v-for="item in memberUserOptions"
                :key="item.userId"
                :label="item.userNickname"
                :value="item.userId"
              >
                <MemberSelectOption :nickname="item.userNickname" :role-name="item.roleName" />
              </ElOption>
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="负责人" prop="currentHandlerUserId">
            <ElSelect v-model="model.currentHandlerUserId" class="w-full" filterable placeholder="请选择负责人">
              <ElOption
                v-for="item in memberUserOptions"
                :key="item.userId"
                :label="item.userNickname"
                :value="item.userId"
              >
                <MemberSelectOption :nickname="item.userNickname" :role-name="item.roleName" />
              </ElOption>
            </ElSelect>
          </ElFormItem>
        </ElCol>
        <ElCol :span="12">
          <ElFormItem label="排序值">
            <ElInputNumber v-model="model.sort" class="w-full" :min="0" :max="9999" placeholder="请输入排序值" />
          </ElFormItem>
        </ElCol>
      </ElRow>
    </ElForm>
  </BusinessFormDialog>
</template>

<style scoped></style>
