<template>
  <div class="project-card" :class="{ 'project-card--list': view === 'list' }" @click="router.push('/projects/' + project.id)">
    <div class="card-top">
      <div class="card-title-row">
        <h2 class="card-name">{{ project.name }}</h2>
      </div>
      <div class="card-top-actions">
        <span class="stage-badge" :class="stageClass(project.status)">{{ $t(statusLabel(project.status)) }}</span>
        <button class="card-del-btn" :title="$t('projects.deleteTitle')" @click.stop="emit('delete', project)">🗑</button>
      </div>
    </div>

    <!-- 描述:max-height + 省略号,展开/收起;list 视图更紧凑(2 行),card 视图宽松(3 行) -->
    <div class="card-desc-wrap" :class="{ 'is-expanded': descExpanded }">
      <p ref="descRef" class="card-desc">{{ stripMd(project.description) }}</p>
      <button
        v-if="descOverflow"
        class="card-desc-toggle"
        @click.stop="descExpanded = !descExpanded"
      >{{ descExpanded ? $t('common.collapse') : $t('common.expand') }}</button>
    </div>

    <!-- 底部信息 -->
    <div class="card-footer">
      <div class="footer-stat">
        <span class="stat-icon">📁</span>
        <span>{{ moduleCount }}</span>
      </div>
      <div class="footer-stat">
        <span class="stat-icon">📅</span>
        <span>{{ formatDate(project.created_at) }}</span>
      </div>
      <div class="footer-stat">
        <span class="stat-icon">🕐</span>
        <span>{{ formatDate(project.last_active_at ?? project.updated_at) }}</span>
      </div>
    </div>

    <!-- 技术栈标签 -->
    <div class="card-tags" v-if="parseStack(project.stack).length">
      <span class="tech-tag" v-for="t in parseStack(project.stack)" :key="t">{{ t }}</span>
    </div>
  </div>
</template>

<script setup lang="ts">
// 项目列表卡片 — 从 Projects.vue 抽出(单卡片渲染 + 导航 + 删除触发)。
// 依赖均为无副作用纯函数 + 共享常量;删除走 emit 交回父组件处理(confirm 弹层 + store 调用)。
// view prop:'list'(紧凑,默认)/'card'(宽松);描述 max-height 截断 + 展开/收起。
import { useRouter } from 'vue-router'
import { ref, onMounted, watch, nextTick } from 'vue'
import { formatDate } from '@/utils/time'
import { parseStack } from '@/utils/project'
import { stripMd } from '@/utils/markdown'
import { moduleApi } from '@/api/module'
import { projectStatusLabel as statusLabel, projectBadgeClass as stageClass } from '@/constants/project'
import type { ProjectRecord } from '@/api/types'

const props = withDefaults(defineProps<{
  project: ProjectRecord
  /** 视图模式:'list'(紧凑,默认)/'card'(宽松);仅影响描述行数阈值与内边距 */
  view?: 'list' | 'card'
}>(), {
  view: 'list',
})
const emit = defineEmits<{
  (e: 'delete', project: ProjectRecord): void
}>()

const router = useRouter()

// 工程数(异步拉取,展示在卡片底部)
const moduleCount = ref(0)
onMounted(async () => {
  try {
    const list = await moduleApi.listProjectModules(props.project.id)
    moduleCount.value = list.length
  } catch { /* 老项目无工程记录不报错 */ }
  // DOM 渲染完成后测描述是否溢出(决定是否显示「展开」)
  await nextTick()
  measureDesc()
})

// ── 描述截断/展开 ──
// descOverflow=true 才渲染「展开/收起」按钮;阈值由 CSS max-height 控制(-webkit-line-clamp),
// 这里只负责测量实际内容高度是否超出 max-height。
const descRef = ref<HTMLParagraphElement | null>(null)
const descOverflow = ref(false)
const descExpanded = ref(false)

function measureDesc() {
  const el = descRef.value
  if (!el) return
  // scrollHeight > clientHeight 说明被 max-height 截断了
  descOverflow.value = el.scrollHeight - el.clientHeight > 1
}

// 描述/视图模式变化后重新测量(描述异步入库或切 view 行数阈值变,按钮显隐需重算)
watch(() => props.project.description, () => nextTick(measureDesc))
watch(() => props.view, () => nextTick(measureDesc))
</script>

<style scoped>
/* 仅迁入卡片自身样式;列表网格/页面壳样式留 Projects.vue(网格布局属列表职责) */
.project-card {
  background: var(--df-bg-card);
  border: 0.5px solid var(--df-border);
  border-radius: var(--df-radius-lg);
  padding: var(--df-pad-panel);
  transition: all 0.15s;
  cursor: pointer;
}
.project-card:hover {
  border-color: var(--df-accent);
}

.card-top {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
}
.card-title-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.card-name { font-size: 17px; font-weight: 500; color: var(--df-text); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

.stage-badge {
  font-size: 12px; font-weight: 500;
  padding: 3px 10px;
  border-radius: var(--df-radius-sm);
}
.stage-design { background: rgba(100,181,246,0.15); color: var(--df-info); }
.stage-coding { background: rgba(108,99,255,0.15); color: var(--df-accent); }
.stage-testing { background: rgba(255,217,61,0.15); color: var(--df-warning); }
.stage-release { background: rgba(100,255,218,0.15); color: var(--df-success); }

.card-desc-wrap {
  position: relative;
  margin-bottom: 16px;
}

.card-desc {
  font-size: 13px;
  color: var(--df-text-secondary);
  line-height: 1.5;
  margin: 0;
  /* 默认截断:2 行(list 视图紧凑,单屏多张)。展开态取消截断。 */
  display: -webkit-box;
  -webkit-box-orient: vertical;
  overflow: hidden;
  -webkit-line-clamp: 2;
}
/* card 视图略宽松:3 行 */
.project-card--list .card-desc { -webkit-line-clamp: 2; }
.project-card:not(.project-card--list) .card-desc { -webkit-line-clamp: 3; }
.card-desc-wrap.is-expanded .card-desc {
  -webkit-line-clamp: unset;
  display: block;
  overflow: visible;
}

/* 展开/收起按钮:右对齐、低调,避免抢卡片点击 */
.card-desc-toggle {
  display: inline-block;
  margin-top: 4px;
  padding: 0;
  background: transparent;
  border: none;
  color: var(--df-accent);
  font-size: 12px;
  cursor: pointer;
  line-height: 1.4;
}
.card-desc-toggle:hover { text-decoration: underline; }

/* list 视图:更紧凑的内边距,单屏容纳更多卡片 */
.project-card--list { padding: calc(var(--df-pad-panel) * 0.7); }

.card-footer {
  display: flex;
  gap: var(--df-gap-grid);
  margin-bottom: 14px;
}
.footer-stat {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: var(--df-text-dim);
}
.stat-icon { font-size: 13px; }

.card-top-actions { display: flex; align-items: center; gap: 8px; }
.card-del-btn {
  background: transparent; border: none; cursor: pointer;
  font-size: 14px; padding: 2px 4px; opacity: 0;
  transition: opacity 0.15s;
}
/* hover 态依赖 .project-card 父级 — scoped 下 :deep 不适用于兄弟伪类,改用 group 思路:卡片 hover 时按钮可见 */
.project-card:hover .card-del-btn { opacity: 0.55; }
.card-del-btn:hover { opacity: 1 !important; }
</style>
