<script setup lang="ts">
import { computed, onActivated, ref, watch } from 'vue';
import { useRouter } from 'vue-router';
import { RDMS_REQ_PRIORITY_DICT_CODE } from '@/constants/dict';
import { OBJECT_CONTEXT_QUERY_KEY } from '@/constants/object-context';
import { fetchGetMyExecutionPage } from '@/service/api';
import DictTag from '@/components/custom/dict-tag.vue';
import { formatDateRange, getExecutionStatusTagType } from '@/views/project/project/execution/shared';
import { buildWorkbenchMyExecutionItems } from '../homepage';
import { useWorkbenchRefresh } from '../composables/use-workbench-refresh';
import WorkbenchModuleCard from './workbench-module-card.vue';

defineOptions({ name: 'WorkbenchMyExecution' });

type MyExecutionItem = Api.Project.MyExecutionItem;

interface Props {
  editing?: boolean;
}
withDefaults(defineProps<Props>(), { editing: false });
defineEmits<{ (e: 'hide'): void }>();

const router = useRouter();

const items = ref<MyExecutionItem[]>([]);

const { loading, refresh } = useWorkbenchRefresh(async () => {
  // pageSize=-1 一次拉取全部当前用户负责的进行中执行；状态/进度过滤由后端完成
  const { data, error } = await fetchGetMyExecutionPage({ pageNo: 1, pageSize: -1 });
  if (error) return;
  items.value = buildWorkbenchMyExecutionItems(data?.list ?? []);
});

// 工作台路由 keepAlive：切回不重挂，用 onActivated 替代 onMounted，每次激活重拉（首挂也会触发，不漏首屏）
onActivated(refresh);

// 按项目归类：未完成执行数多的项目在前；项目内按计划结束日升序（更紧的在前）
const groups = computed<Array<{ projectId: string; projectName: string; items: MyExecutionItem[] }>>(() => {
  const map = new Map<string, { projectId: string; projectName: string; items: MyExecutionItem[] }>();
  items.value.forEach(item => {
    if (!map.has(item.projectId)) {
      map.set(item.projectId, { projectId: item.projectId, projectName: item.projectName, items: [] });
    }
    map.get(item.projectId)!.items.push(item);
  });
  const groupsArr = Array.from(map.values());
  groupsArr.forEach(g => {
    g.items.sort((a, b) => {
      const av = a.plannedEndDate ? new Date(a.plannedEndDate).getTime() : Number.POSITIVE_INFINITY;
      const bv = b.plannedEndDate ? new Date(b.plannedEndDate).getTime() : Number.POSITIVE_INFINITY;
      return av - bv;
    });
  });
  return groupsArr.sort((a, b) => b.items.length - a.items.length);
});

// 手风琴：单开，默认展开第一个项目（执行最多）；展开项消失时回退到第一个
const expandedProjectId = ref<string>('');
watch(
  groups,
  list => {
    if (!list.length) {
      expandedProjectId.value = '';
      return;
    }
    if (!list.some(g => g.projectId === expandedProjectId.value)) {
      expandedProjectId.value = list[0].projectId;
    }
  },
  { immediate: true }
);

function toggleProject(projectId: string) {
  expandedProjectId.value = expandedProjectId.value === projectId ? '' : projectId;
}

function goProjectExecutionPool(projectId: string) {
  router.push({
    path: '/project/project/execution',
    query: { [OBJECT_CONTEXT_QUERY_KEY]: projectId }
  });
}

function goRequirementDetail(item: MyExecutionItem) {
  if (!item.projectRequirementId) return;
  router.push({
    path: '/project/project/requirement',
    query: {
      [OBJECT_CONTEXT_QUERY_KEY]: item.projectId,
      requirementId: item.projectRequirementId
    }
  });
}
</script>

<template>
  <WorkbenchModuleCard
    title="我负责的执行"
    icon="mdi:flag-checkered"
    :badge-count="items.length"
    :editing="editing"
    @hide="$emit('hide')"
    @refresh="refresh"
  >
    <div v-if="items.length" v-loading="loading" class="exec-groups">
      <section
        v-for="group in groups"
        :key="group.projectId"
        class="exec-group"
        :class="{ 'is-open': expandedProjectId === group.projectId }"
      >
        <header
          class="exec-group__head"
          role="button"
          tabindex="0"
          :aria-expanded="expandedProjectId === group.projectId"
          @click="toggleProject(group.projectId)"
          @keydown.enter.prevent="toggleProject(group.projectId)"
        >
          <SvgIcon
            icon="mdi:chevron-right"
            class="exec-group__chevron"
            :class="{ 'is-open': expandedProjectId === group.projectId }"
          />
          <SvgIcon icon="mdi:briefcase-outline" class="exec-group__icon" />
          <span class="exec-group__name" :title="group.projectName">{{ group.projectName }}</span>
          <span class="exec-group__count">{{ group.items.length }}</span>
          <ElButton
            link
            size="small"
            class="exec-group__go"
            :title="`进入「${group.projectName}」执行池`"
            @click.stop="goProjectExecutionPool(group.projectId)"
          >
            <SvgIcon icon="mdi:open-in-new" />
          </ElButton>
        </header>
        <ul v-show="expandedProjectId === group.projectId" class="exec-list">
          <li v-for="item in group.items" :key="item.id" class="exec-item">
            <div class="exec-head">
              <span class="exec-name" :title="item.executionName">{{ item.executionName }}</span>
              <DictTag
                class="exec-head__tag"
                :dict-code="RDMS_REQ_PRIORITY_DICT_CODE"
                :value="item.priority"
                effect="light"
                size="small"
              />
              <ElTag
                class="exec-head__tag"
                size="small"
                :type="getExecutionStatusTagType(item.statusCode)"
                effect="light"
              >
                {{ item.statusName }}
              </ElTag>
            </div>
            <div class="exec-meta">
              <div class="exec-meta__row">
                <SvgIcon icon="mdi:flag-outline" class="exec-meta__icon" />
                <span class="exec-meta__text">
                  计划 {{ formatDateRange(item.plannedStartDate, item.plannedEndDate) }}
                </span>
              </div>
              <div class="exec-meta__row">
                <SvgIcon icon="mdi:calendar-outline" class="exec-meta__icon" />
                <span class="exec-meta__text">
                  实际 {{ formatDateRange(item.actualStartDate, item.actualEndDate) }}
                </span>
              </div>
              <div v-if="item.projectRequirementId && item.projectRequirementName" class="exec-meta__row">
                <SvgIcon icon="mdi:link-variant" class="exec-meta__icon" />
                <span class="exec-meta__label">需求</span>
                <span
                  class="exec-meta__text exec-meta__link"
                  role="button"
                  tabindex="0"
                  :title="item.projectRequirementName"
                  @click="goRequirementDetail(item)"
                  @keydown.enter.prevent="goRequirementDetail(item)"
                >
                  {{ item.projectRequirementName }}
                </span>
              </div>
            </div>
            <ElProgress :percentage="item.progressRate" :stroke-width="6" />
          </li>
        </ul>
      </section>
    </div>
    <div v-else v-loading="loading" class="exec-empty">
      <ElEmpty description="暂无进行中的执行" :image-size="60" />
    </div>
  </WorkbenchModuleCard>
</template>

<style scoped>
.exec-groups {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.exec-empty {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}
.exec-group__head {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 8px 10px;
  border-radius: 6px;
  /* 常驻分组底色，明显区别于下方执行项卡片 */
  background: var(--el-fill-color-light);
  border-left: 3px solid transparent;
  cursor: pointer;
  user-select: none;
  transition:
    background 0.16s ease,
    border-color 0.16s ease;
}
.exec-group__head:hover,
.exec-group__head:focus-visible {
  background: var(--el-fill-color);
  outline: none;
}
.exec-group.is-open > .exec-group__head {
  background: var(--el-color-primary-light-9);
  border-left-color: var(--el-color-primary);
}
.exec-group__chevron {
  flex-shrink: 0;
  font-size: 15px;
  color: var(--el-text-color-secondary);
  transition: transform 0.18s ease;
}
.exec-group__chevron.is-open {
  transform: rotate(90deg);
}
.exec-group__icon {
  flex-shrink: 0;
  font-size: 15px;
  /* 项目 icon 用主色，与项目管理业务域图标一致且更醒目 */
  color: var(--el-color-primary);
}
.exec-group__name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-size: 13.5px;
  font-weight: 600;
  color: var(--el-text-color-primary);
  letter-spacing: 0.01em;
}
.exec-group.is-open .exec-group__name {
  color: var(--el-color-primary);
}
.exec-group__go {
  flex-shrink: 0;
}
.exec-group__count {
  flex-shrink: 0;
  min-width: 22px;
  height: 18px;
  padding: 0 6px;
  border-radius: 9px;
  background: var(--el-fill-color);
  color: var(--el-text-color-secondary);
  font-size: 11px;
  font-weight: 600;
  text-align: center;
  line-height: 18px;
}
.exec-list {
  list-style: none;
  margin: 4px 0 2px;
  padding: 0 2px 0 22px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.exec-item {
  padding: 9px 10px;
  border: 1px solid var(--el-border-color-lighter);
  border-radius: 6px;
  background: var(--el-fill-color-blank);
  transition:
    border-color 0.16s ease,
    background 0.16s ease;
}
.exec-item:hover {
  border-color: var(--el-color-primary-light-5);
  background: var(--el-color-primary-light-9);
}
.exec-head {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 6px;
}
.exec-name {
  flex: 1;
  min-width: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  font-weight: 600;
  font-size: 13px;
  color: var(--el-text-color-primary);
}
.exec-head__tag {
  flex: 0 0 auto;
}
.exec-meta {
  display: flex;
  flex-direction: column;
  gap: 3px;
  margin-bottom: 8px;
}
.exec-meta__row {
  display: flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
  font-size: 12px;
  color: var(--el-text-color-secondary);
}
.exec-meta__icon {
  flex-shrink: 0;
  font-size: 13px;
  color: var(--el-text-color-placeholder);
}
.exec-meta__label {
  flex-shrink: 0;
  color: var(--el-text-color-secondary);
}
.exec-meta__text {
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
}
.exec-meta__link {
  color: var(--el-color-primary);
  cursor: pointer;
}
.exec-meta__link:hover,
.exec-meta__link:focus-visible {
  text-decoration: underline;
  outline: none;
}
</style>
