<template>
  <CrmDrawer v-model:show="show" :width="1000" :footer="false" :title="t('module.businessManage.businessStepSet')">
    <div class="mb-[16px] text-[16px] font-semibold">{{ t('module.businessManage.businessStepConfig') }}</div>
    <div class="bg-[var(--text-n9)] p-[16px]">
      <div class="flex items-center gap-[8px]">
        <div class="w-[12px]"></div>
        <div v-for="(ele, index) of title" :key="`ele-${index}`" class="w-full flex-1">{{ ele }}</div>
        <div class="w-[68px]"></div>
      </div>
      <CrmBatchForm
        ref="batchFormRef"
        :models="formItemModel"
        :default-list="form.list"
        validate-when-add
        draggable
        class="!p-0"
        :move="handleMove"
        @save-row="handleSave"
        @drag="dragEnd"
        @cancel-row="handleCancelRow"
      >
        <template #extra="{ element }">
          <CrmMoreAction
            :options="getDropdownOptions(element)"
            placement="bottom"
            @select="handleMoreSelect($event, element)"
          >
            <n-button ghost class="px-[7px]">
              <template #icon>
                <CrmIcon type="iconicon_ellipsis" :size="16" />
              </template>
            </n-button>
          </CrmMoreAction>
          <div v-if="getDropdownOptions(element).length === 0" class="w-[32px]"></div>
        </template>
      </CrmBatchForm>
    </div>
    <div class="mb-[16px] mt-[24px] text-[16px] font-semibold">
      {{ t('module.businessManage.businessStepRollbackConfig') }}
    </div>
    <div class="flex items-center gap-[8px]">
      <n-switch v-model:value="form.runningStageRollback" @update-value="handleSwitchChange" />
      {{ t('module.businessManage.runningStageRollback') }}
      <n-tooltip trigger="hover" placement="right">
        <template #trigger>
          <CrmIcon
            type="iconicon_help_circle"
            :size="16"
            class="cursor-pointer text-[var(--text-n4)] hover:text-[var(--primary-1)]"
          />
        </template>
        {{ t('module.businessManage.runningStageRollbackTip') }}
      </n-tooltip>
    </div>
    <div class="mt-[16px] flex items-center gap-[8px]">
      <n-switch v-model:value="form.completedStageRollback" @update-value="handleSwitchChange" />
      {{ t('module.businessManage.completedStageRollback') }}
      <n-tooltip trigger="hover" placement="right">
        <template #trigger>
          <CrmIcon
            type="iconicon_help_circle"
            :size="16"
            class="cursor-pointer text-[var(--text-n4)] hover:text-[var(--primary-1)]"
          />
        </template>
        {{ t('module.businessManage.completedStageRollbackTip') }}
      </n-tooltip>
    </div>
  </CrmDrawer>
</template>

<script setup lang="ts">
  import { NButton, NSwitch, NTooltip, useMessage } from 'naive-ui';

  import { FieldTypeEnum } from '@lib/shared/enums/formDesignEnum';
  import { useI18n } from '@lib/shared/hooks/useI18n';
  import { getGenerateId } from '@lib/shared/method';
  import { StageConfigItem } from '@lib/shared/models/opportunity';

  import CrmDrawer from '@/components/pure/crm-drawer/index.vue';
  import CrmIcon from '@/components/pure/crm-icon-font/index.vue';
  import CrmMoreAction from '@/components/pure/crm-more-action/index.vue';
  import { ActionsItem } from '@/components/pure/crm-more-action/type';
  import CrmBatchForm from '@/components/business/crm-batch-form/index.vue';
  import { FormItemModel } from '@/components/business/crm-batch-form/types';

  import {
    addOpportunityStage,
    deleteOpportunityStage,
    getOpportunityStageConfig,
    sortOpportunityStage,
    updateOpportunityStage,
    updateOpportunityStageRollback,
  } from '@/api/modules';

  const { t } = useI18n();
  const Message = useMessage();

  const show = defineModel<boolean>('visible', {
    required: true,
  });

  const batchFormRef = ref<InstanceType<typeof CrmBatchForm>>();
  const form = ref<any>({
    runningStageRollback: true,
    completedStageRollback: false,
    list: [],
  });

  const title = [t('opportunity.stage'), t('opportunity.win'), t('opportunity.stageType')];

  const formItemModel = ref<FormItemModel[]>([
    {
      path: 'name',
      type: FieldTypeEnum.INPUT,
      formItemClass: 'w-full flex-initial',
      inputProps: {
        maxlength: 16,
      },
      rule: [
        {
          required: true,
          message: t('common.notNull', { value: '' }),
        },
      ],
    },
    {
      path: 'rate',
      type: FieldTypeEnum.INPUT_NUMBER,
      formItemClass: 'w-full flex-initial',
      numberProps: {
        min: 0,
        max: 100,
        precision: 0,
        disabledFunction(row) {
          return row.type === 'END';
        },
      },
      rule: [
        {
          required: true,
          message: t('common.notNull', { value: '' }),
        },
      ],
    },
    {
      path: 'type',
      type: FieldTypeEnum.SELECT,
      formItemClass: 'w-full flex-initial',
      selectProps: {
        disabledFunction: () => true,
        disabledTooltipFunction: () => t('opportunity.stageTypeDisabledChange'),
        options: [
          { label: t('common.inProgress'), value: 'AFOOT' },
          { label: t('common.complete'), value: 'END' },
        ],
      },
    },
  ]);

  function getDropdownOptions(element: Record<string, any>): ActionsItem[] {
    if (element.type === 'END') {
      return [];
    }

    const minAfootCount = form.value.list.filter((item: any) => item.type === 'AFOOT').length === 1;
    if (minAfootCount) {
      // 至少保留一个进行中的状态
      return [
        { label: t('module.businessManage.insetBefore'), key: 'before' },
        { label: t('module.businessManage.insetAfter'), key: 'after' },
      ];
    }
    if (form.value.list.length === 10) {
      return [
        {
          label: t('common.delete'),
          key: 'delete',
          danger: true,
          disabled: element.stageHasData,
          tooltipContent: element.stageHasData ? t('module.businessManage.stageHasData') : '',
        },
      ];
    }
    return [
      { label: t('module.businessManage.insetBefore'), key: 'before' },
      { label: t('module.businessManage.insetAfter'), key: 'after' },
      { type: 'divider' },
      {
        label: t('common.delete'),
        key: 'delete',
        danger: true,
        disabled: element.stageHasData,
        tooltipContent: element.stageHasData ? t('module.businessManage.stageHasData') : '',
      },
    ];
  }

  async function handleMoreSelect(action: ActionsItem, element: Record<string, any>) {
    const index = form.value.list.findIndex((item: any) => item.id === element.id);
    const id = getGenerateId();
    if (action.key === 'before') {
      batchFormRef.value?.formValidate(() => {
        form.value.list.splice(index, 0, { _key: id, name: '', rate: null, type: 'AFOOT', editing: true });
      });
    } else if (action.key === 'after') {
      batchFormRef.value?.formValidate(() => {
        form.value.list.splice(index + 1, 0, {
          _key: id,
          name: '',
          rate: null,
          type: 'AFOOT',
          editing: true,
        });
      });
    } else if (action.key === 'delete') {
      await deleteOpportunityStage(element.id);
      form.value.list.splice(index, 1);
    }
  }

  function handleCancelRow(index: number) {
    form.value.list.splice(index, 1);
  }

  async function handleSwitchChange() {
    try {
      await updateOpportunityStageRollback({
        afootRollBack: form.value.runningStageRollback,
        endRollBack: form.value.completedStageRollback,
      });
      Message.success(t('common.operationSuccess'));
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }

  async function init() {
    try {
      const res = await getOpportunityStageConfig();
      form.value = {
        runningStageRollback: res.afootRollBack,
        completedStageRollback: res.endRollBack,
        list: res.stageConfigList.map((item: StageConfigItem) => ({
          ...item,
          _key: item.id,
          rate: Number(item.rate),
          editing: false,
          draggable: item.type !== 'END',
        })),
      };
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }

  async function dragEnd(event: any) {
    if (form.value.list.length === 1) return;
    try {
      const { newIndex, oldIndex } = event;
      if (newIndex === oldIndex) return;

      const newList = [...form.value.list];
      const [movedItem] = newList.splice(oldIndex, 1);
      newList.splice(newIndex, 0, movedItem);

      await sortOpportunityStage(newList.map((e: StageConfigItem) => e.id));
      init();
      Message.success(t('common.operationSuccess'));
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }

  async function handleSave(element: Record<string, any>, done: () => void, index: number) {
    try {
      const params = {
        id: element?.id,
        name: element.name,
        rate: element.rate,
      };
      if (element.id) {
        await updateOpportunityStage(params);
        done();
      } else {
        await addOpportunityStage({
          ...params,
          type: element.type,
          dropPosition: form.value.list[index - 1] ? 1 : -1,
          targetId: form.value.list[index - 1]?.id || form.value.list[index + 1]?.id,
        });
        done();
      }
      init();
      Message.success(t('common.operationSuccess'));
    } catch (error) {
      // eslint-disable-next-line no-console
      console.log(error);
    }
  }

  function handleMove(evt: any) {
    const fromEl = evt.from;
    const draggedEl = evt.dragged;
    const relatedEl = evt.related;

    const children = Array.from(fromEl.children);
    const draggedIndex = children.indexOf(draggedEl);
    const targetIndex = children.indexOf(relatedEl);

    // 禁止拖拽最后两个
    if (draggedIndex >= form.value.list.length - 2) return false;

    // 禁止拖放到最后两个之后
    if (targetIndex >= form.value.list.length - 2) return false;

    // 允许其他情况
    return true;
  }

  watch(
    () => show.value,
    (val) => {
      if (val) {
        init();
      }
    }
  );
</script>

<style lang="less" scoped></style>
