<script lang="ts">
/** 项目列表左栏导航键：项目状态编码（状态机动态下发，不再用字面量联合约束）+ 'all' + 'orphan' */
</script>

<script setup lang="ts">
import type { Component } from 'vue';
import { computed } from 'vue';
import {
  Box,
  CircleCheckFilled,
  DeleteFilled,
  Document,
  DocumentAdd,
  Menu,
  QuestionFilled,
  VideoPause,
  VideoPlay
} from '@element-plus/icons-vue';
export type ProjectListNavKey = string;

defineOptions({ name: 'ProjectStatusRail' });

type NavTone = 'sky' | 'teal' | 'slate' | 'amber' | 'rose' | 'indigo' | 'violet';

interface NavItemView {
  key: ProjectListNavKey;
  label: string;
  tone: NavTone;
  icon: Component;
  count: number;
}

interface Props {
  /** 状态看板项（overview-summary items，后端已按 sort 升序） */
  items: Api.Project.OverviewStatusItem[];
  /** "全部"口径总数（直接用后端 total，前端不自行求和或排除） */
  total: number;
  /** 游离项目计数（>0 才显示游离入口） */
  orphanCount: number;
  selected: ProjectListNavKey;
}

const props = defineProps<Props>();

interface Emits {
  (e: 'change', key: ProjectListNavKey): void;
}

const emit = defineEmits<Emits>();

interface StatusVisualMeta {
  tone: NavTone;
  icon: Component;
}

/** 状态视觉资产（icon/tone）是前端本地映射；状态名直接渲染后端 statusName，不做本地名称映射 */
const STATUS_VISUALS: Record<string, StatusVisualMeta> = {
  active: { tone: 'teal', icon: VideoPlay },
  pending: { tone: 'indigo', icon: DocumentAdd },
  paused: { tone: 'amber', icon: VideoPause },
  completed: { tone: 'teal', icon: CircleCheckFilled },
  cancelled: { tone: 'rose', icon: DeleteFilled },
  archived: { tone: 'slate', icon: Box }
};

/** 状态机新增状态未配置视觉资产时的默认兜底：通用图标 + 中性色 */
const DEFAULT_STATUS_VISUAL: StatusVisualMeta = { tone: 'slate', icon: Document };

/**
 * 终态分区（分隔线下方）是前端视觉决策的写死名单：completed 在状态机里也可能是终态但业务上放主区，
 * 因此不能用后端 terminal 标志分组。
 */
const TERMINAL_SECTION_CODES = new Set<string>(['cancelled', 'archived']);

const ORPHAN_ITEM = {
  key: 'orphan',
  label: '游离项目',
  tone: 'violet',
  icon: QuestionFilled
} as const;

function toNavItem(item: Api.Project.OverviewStatusItem): NavItemView {
  const visual = STATUS_VISUALS[item.statusCode] ?? DEFAULT_STATUS_VISUAL;

  return {
    key: item.statusCode,
    label: item.statusName,
    tone: visual.tone,
    icon: visual.icon,
    count: item.count
  };
}

const mainItems = computed<NavItemView[]>(() => [
  { key: 'all', label: '全部项目', tone: 'sky', icon: Menu, count: props.total },
  ...props.items.filter(item => !TERMINAL_SECTION_CODES.has(item.statusCode)).map(toNavItem)
]);

const terminalItems = computed<NavItemView[]>(() =>
  props.items.filter(item => TERMINAL_SECTION_CODES.has(item.statusCode)).map(toNavItem)
);

function handleClick(key: ProjectListNavKey) {
  emit('change', key);
}
</script>

<template>
  <ElCard class="project-status-rail card-wrapper">
    <div class="project-status-rail__list">
      <button
        v-for="item in mainItems"
        :key="item.key"
        type="button"
        class="project-status-item"
        :class="[`project-status-item--${item.tone}`, { 'is-active': selected === item.key }]"
        :aria-pressed="selected === item.key"
        @click="handleClick(item.key)"
      >
        <div class="project-status-item__icon">
          <ElIcon>
            <component :is="item.icon" />
          </ElIcon>
        </div>
        <div class="project-status-item__main">
          <div class="project-status-item__top">
            <strong>{{ item.label }}</strong>
            <em>{{ item.count }}</em>
          </div>
        </div>
      </button>

      <div v-if="terminalItems.length" class="project-status-rail__divider"></div>

      <button
        v-for="item in terminalItems"
        :key="item.key"
        type="button"
        class="project-status-item"
        :class="[`project-status-item--${item.tone}`, { 'is-active': selected === item.key }]"
        :aria-pressed="selected === item.key"
        @click="handleClick(item.key)"
      >
        <div class="project-status-item__icon">
          <ElIcon>
            <component :is="item.icon" />
          </ElIcon>
        </div>
        <div class="project-status-item__main">
          <div class="project-status-item__top">
            <strong>{{ item.label }}</strong>
            <em>{{ item.count }}</em>
          </div>
        </div>
      </button>

      <template v-if="orphanCount > 0">
        <div class="project-status-rail__divider"></div>
        <button
          type="button"
          class="project-status-item"
          :class="[`project-status-item--${ORPHAN_ITEM.tone}`, { 'is-active': selected === 'orphan' }]"
          :aria-pressed="selected === 'orphan'"
          @click="handleClick('orphan')"
        >
          <div class="project-status-item__icon">
            <ElIcon>
              <component :is="ORPHAN_ITEM.icon" />
            </ElIcon>
          </div>
          <div class="project-status-item__main">
            <div class="project-status-item__top">
              <strong>{{ ORPHAN_ITEM.label }}</strong>
              <em>{{ orphanCount }}</em>
            </div>
          </div>
        </button>
      </template>
    </div>
  </ElCard>
</template>

<style lang="scss" scoped>
.project-status-rail {
  overflow: hidden;
  border: 1px solid rgb(226 232 240 / 92%);
  background:
    radial-gradient(circle at top left, rgb(14 165 233 / 8%), transparent 36%),
    linear-gradient(180deg, rgb(255 255 255 / 99%), rgb(248 250 252 / 97%));
}

.project-status-rail__list {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.project-status-rail__divider {
  height: 1px;
  margin: 2px 4px;
  background: var(--el-border-color-lighter);
}

.project-status-item {
  display: flex;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 12px 14px;
  border: 1px solid rgb(226 232 240 / 90%);
  border-radius: 18px;
  background-color: rgb(255 255 255 / 86%);
  text-align: left;
  cursor: pointer;
  transition:
    transform 0.2s ease,
    border-color 0.2s ease,
    box-shadow 0.2s ease;
}

.project-status-item:hover {
  transform: translateY(-1px);
  border-color: rgb(148 163 184 / 60%);
}

.project-status-item.is-active {
  border-color: rgb(14 165 233 / 40%);
  box-shadow: 0 10px 24px rgb(14 165 233 / 8%);
}

.project-status-item__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 14px;
  font-size: 20px;
}

.project-status-item__main {
  min-width: 0;
  flex: 1;
}

.project-status-item__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.project-status-item__top strong {
  color: rgb(15 23 42 / 94%);
  font-size: 15px;
  font-weight: 700;
}

.project-status-item__top em {
  color: rgb(15 23 42 / 88%);
  font-size: 18px;
  font-style: normal;
  font-weight: 700;
}

.project-status-item--sky .project-status-item__icon {
  background-color: rgb(240 249 255 / 96%);
  color: rgb(2 132 199 / 96%);
}

.project-status-item--teal .project-status-item__icon {
  background-color: rgb(240 253 250 / 96%);
  color: rgb(15 118 110 / 96%);
}

.project-status-item--slate .project-status-item__icon {
  background-color: rgb(241 245 249 / 96%);
  color: rgb(51 65 85 / 92%);
}

.project-status-item--amber .project-status-item__icon {
  background-color: rgb(255 251 235 / 96%);
  color: rgb(217 119 6 / 92%);
}

.project-status-item--rose .project-status-item__icon {
  background-color: rgb(255 241 242 / 96%);
  color: rgb(225 29 72 / 92%);
}

.project-status-item--indigo .project-status-item__icon {
  background-color: rgb(238 242 255 / 96%);
  color: rgb(79 70 229 / 92%);
}

.project-status-item--violet .project-status-item__icon {
  background-color: rgb(245 243 255 / 96%);
  color: rgb(124 58 237 / 92%);
}

@media (width <= 1280px) {
  .project-status-item__top {
    align-items: flex-start;
    flex-direction: column;
  }
}
</style>
