<!--
文件: timeLine.vue
功能: 渲染流程审批时间线（TimeLine）组件，用于展示流程中各审批节点及其人员、状态、审批意见等信息。
主要逻辑:
- 根据节点类型 (`NodeType`) 映射 SVG 图标与颜色，使用 `nodeTypeSvgMap` 提供每类节点的图标与主题色。
- 使用 `statusIconMap` / `statusIconMap2` 将任务/节点状态映射为不同的颜色与图标，用于节点右下角小图标和任务标签内的状态指示。
- 提供 `getApprovalNodeImg`、`getApprovalNodeIcon`、`getApprovalNodeColor` 等工具函数，用于模板中决定节点图标、状态图标与配色显示逻辑。
- 管理可选审批人 `approvalUser`，支持通过 `selectUser` 弹窗选择审批人，选择结果会触发 `selectUserConfirm` 事件通知父组件。
- 在模板中渲染时间线：每个节点显示图标、名称、候选人或已分配任务、审批意见等；当节点支持自定义审批人时显示可编辑的用户标签与添加按钮。
- 组件通过 `props` 接收 `activityNodes`、`showStatusIcon`、`enableApproveUserSelect` 等参数以控制展示与交互。
-->

<script setup lang="ts">
import type { User } from '../interface';
import { ArrowDownOutlined, CheckOutlined, ClockCircleOutlined, CloseOutlined, DeleteOutlined, LoadingOutlined, MinusOutlined, UserAddOutlined } from '@ant-design/icons-vue';
import { selectUser } from '@pubinfo/module-rbac';
import { h } from 'vue';
import auditorSvg from '@/assets/bpm/auditor.svg';
import childProcessSvg from '@/assets/bpm/child-process.svg';
import conditionSvg from '@/assets/bpm/condition.svg';
import copySvg from '@/assets/bpm/copy.svg';
import finishSvg from '@/assets/bpm/finish.svg';
import parallelSvg from '@/assets/bpm/parallel.svg';
import starterSvg from '@/assets/bpm/starter.svg';
import transactorSvg from '@/assets/bpm/transactor.svg';
import { isEmpty } from '@/utils/fun';
import { CandidateStrategy } from '../../flow-create/flow-model/createComponents/flow/ts/enum';
import { NodeType, TaskStatusEnum } from '../enum';

defineOptions({
  name: 'TimeLineComponent',
});

const props = withDefaults(
  defineProps<{
    activityNodes: any[] // 审批节点信息
    showStatusIcon?: boolean // 是否显示头像右下角状态图标
    enableApproveUserSelect?: boolean // 是否开启审批人自选功能
  }>(),
  {
    showStatusIcon: true, // 默认值为 true
    enableApproveUserSelect: false, // 默认值为 false
  },
);

const emit = defineEmits<{
  selectUserConfirm: [id: any, userList: any[]]
}>();

const nodeTypeSvgMap: Record<number, { color: string, svg: any }> = {
  // 结束节点
  [NodeType.END_EVENT_NODE]: { color: '#909398', svg: finishSvg },
  // 发起人节点
  [NodeType.START_USER_NODE]: { color: '#909398', svg: starterSvg },
  // 审批人节点
  [NodeType.USER_TASK_NODE]: { color: '#ff943e', svg: auditorSvg },
  // 办理人节点
  [NodeType.TRANSACTOR_NODE]: { color: '#ff943e', svg: transactorSvg },
  // 抄送人节点
  [NodeType.COPY_TASK_NODE]: { color: '#3296fb', svg: copySvg },
  // 条件分支节点
  [NodeType.CONDITION_NODE]: { color: '#14bb83', svg: conditionSvg },
  // 并行分支节点
  [NodeType.PARALLEL_BRANCH_NODE]: { color: '#14bb83', svg: parallelSvg },
  // 子流程节点
  [NodeType.CHILD_PROCESS_NODE]: { color: '#14bb83', svg: childProcessSvg },
};

// 审批节点
const statusIconMap2: Record<string, { color: string, icon: any }> = {
  // 跳过
  '-2': { color: '#cccccc', icon: ArrowDownOutlined },
  // 未开始
  '-1': { color: '#909398', icon: ClockCircleOutlined },
  // 待审批
  '0': { color: '#00b32a', icon: LoadingOutlined },
  // 审批中
  '1': { color: '#448ef7', icon: LoadingOutlined },
  // 审批通过
  '2': { color: '#00b32a', icon: CheckOutlined },
  // 审批不通过
  '3': { color: '#f46b6c', icon: CloseOutlined },
  // 取消
  '4': { color: '#cccccc', icon: DeleteOutlined },
  // 退回
  '5': { color: '#f46b6c', icon: MinusOutlined },
  // 委派中
  '6': { color: '#448ef7', icon: LoadingOutlined },
  // 审批通过中
  '7': { color: '#00b32a', icon: CheckOutlined },
};

// 审批时间线上的节点
const statusIconMap: Record<string, { color: string, icon: any }> = {
  // 跳过
  '-2': { color: '#909398', icon: ArrowDownOutlined },
  // 审批未开始
  '-1': { color: '#909398', icon: ClockCircleOutlined },
  '0': { color: '#00b32a', icon: ClockCircleOutlined },
  // 审批中
  '1': { color: '#448ef7', icon: LoadingOutlined },
  // 审批通过
  '2': { color: '#00b32a', icon: CheckOutlined },
  // 审批不通过
  '3': { color: '#f46b6c', icon: CloseOutlined },
  // 已取消
  '4': { color: '#cccccc', icon: DeleteOutlined },
  // 退回
  '5': { color: '#f46b6c', icon: MinusOutlined },
  // 委派中
  '6': { color: '#448ef7', icon: LoadingOutlined },
  // 审批通过中
  '7': { color: '#00b32a', icon: CheckOutlined },
};

// timeline时间线上icon图标
function getApprovalNodeImg(nodeType: NodeType) {
  return nodeTypeSvgMap[nodeType]?.svg;
}

function getApprovalNodeIcon(taskStatus: number, nodeType: NodeType) {
  if (taskStatus === TaskStatusEnum.NOT_START) {
    return statusIconMap[taskStatus]?.icon;
  }

  if (
    nodeType === NodeType.START_USER_NODE
    || nodeType === NodeType.USER_TASK_NODE
    || nodeType === NodeType.TRANSACTOR_NODE
    || nodeType === NodeType.CHILD_PROCESS_NODE
    || nodeType === NodeType.END_EVENT_NODE
  ) {
    return statusIconMap[taskStatus]?.icon;
  }
}

// 只有只有状态是 -1、0、1 才展示头像右小角状态小icon
// const onlyStatusIconShow = [-1, 0, 1];

function getApprovalNodeColor(taskStatus: number) {
  return statusIconMap[taskStatus]?.color;
}

interface UserGroupArray {
  [key: string]: User[]
}

const approvalUser = ref<UserGroupArray>({});

function openUserModel(id: string, list: User[]) {
  selectUser({
    multiple: true,
    modelValue: list,
    onSubmit: (selectedUsers: any[]) => {
      // console.log('---selectedUsers---', selectedUsers);
      approvalUser.value[id] = selectedUsers.map(user => ({
        orgId: user.orgId,
        userId: user.userId,
        userName: user.userName,
      }));
    },
  });
}

function deleteUser(id: string, user: User) {
  approvalUser.value[id] = approvalUser.value[id].filter(u => u.userId !== user.userId);
}

watch(
  approvalUser,
  (newVal) => {
    // console.log('approvalUser变化：', newVal);
    for (const key in newVal) {
      emit('selectUserConfirm', key, newVal[key]);
    }
  },
  { deep: true },
);
</script>

<template>
  <a-timeline>
    <a-timeline-item v-for="(item, index) in props.activityNodes" :key="index">
      <template #dot>
        <div class="rounded-full border border-solid border-#dedede w-30px h-30px flex justify-center items-center bg-#3f73f7 p-5px">
          <img class="w-full h-full" :src="getApprovalNodeImg(item.nodeType)" alt="">
          <div class="position-absolute top-17px left-17px rounded-full flex items-center p-2px border-2 border-white border-solid" :style="{ backgroundColor: getApprovalNodeColor(item.status) }">
            <component :is="getApprovalNodeIcon(item.status, item.nodeType)" :style="{ fontSize: '10px', color: '#ffffff' }" />
          </div>
        </div>
      </template>
      <div>{{ item.name }}</div>
      <!-- 需要自定义选择审批人 -->
      <div
        v-if="
          isEmpty(item.tasks)
            && ((CandidateStrategy.START_USER_SELECT === item.candidateStrategy
              && isEmpty(item.candidateUsers))
              || (props.enableApproveUserSelect
                && CandidateStrategy.APPROVE_USER_SELECT === item.candidateStrategy))
        "
        class="flex flex-wrap gap2 items-center"
      >
        <a-button :icon="h(UserAddOutlined)" @click="openUserModel(item.id, approvalUser[item.id])" />
        <a-tag v-for="user in approvalUser[item.id]" :key="user.userId" closable @close="deleteUser(item.id, user)">
          {{ user.userName }}
        </a-tag>
      </div>
      <div v-else class="inline-block py-14px">
        <div v-for="(task, idx) in item.tasks" :key="idx" class="flex flex-col pr-2 gap2">
          <div v-if="task.assigneeUser || task.ownerUser">
            <div class="inline-block relative">
              <template v-if="task.assigneeUser?.avatar || task.assigneeUser?.nickname">
                <a-tag class="inline-block">
                  {{ task.assigneeUser?.nickname }}
                </a-tag>
              </template>
              <template v-else-if="task.ownerUser?.avatar || task.ownerUser?.nickname">
                <a-tag class="inline-block">
                  {{ task.ownerUser?.nickname }}
                </a-tag>
              </template>
              <!-- 信息：任务 ICON（固定在标签右下角） -->
              <div class="position-absolute right-2px bottom-[-4px] rounded-full flex items-center p-2px border-2 border-white border-solid" :style="{ backgroundColor: statusIconMap2[task.status]?.color }">
                <component :is="statusIconMap2[task.status]?.icon" :style="{ fontSize: '8px', color: '#ffffff' }" />
              </div>
            </div>
          </div>
          <div
            v-if="task.reason && [NodeType.USER_TASK_NODE, NodeType.END_EVENT_NODE].includes(item.nodeType)"
            class="text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
          >
            <!-- TODO lesan：这里如果是办理，需要是办理意见 -->
            审批意见：{{ task.reason }}
          </div>
          <!-- <div
                v-if="task.signPicUrl && item.nodeType === NodeType.USER_TASK_NODE"
                class="text-#a5a5a5 text-13px mt-1 w-full bg-#f8f8fa p2 rounded-md"
              >
                签名：
                <el-image
                  class="w-90px h-40px ml-5px"
                  :src="task.signPicUrl"
                  :preview-src-list="[task.signPicUrl]"
                />
              </div> -->
        </div>
        <a-tag v-for="user in item.candidateUsers" :key="user.id">
          {{ user.nickname }}
        </a-tag>
      </div>
    </a-timeline-item>
  </a-timeline>
</template>
